CubeResGroupHandle使用说明CubeResGroupHandle用于在分离模式下对AI Core计算资源分组。分组后开发者可以对不同的分组指定不同的计算任务。一个AI Core分组可包含多个AIV和AICAIV和AIC之间采取Client和Server架构进行任务处理。AIV为Client每一个Cube计算任务为一个消息AIV发送消息至消息队列AIC作为Server遍历消息队列的消息根据消息类型及内容执行对应的计算任务。一个CubeResGroupHandle中可以有一个或多个AIC同一个AIC只能属于一个CubeResGroupHandleAIV无此限制即同一个AIV可以属于多个CubeResGroupHandle。如下图所示CubeResGroupHandle1中有2个AIC10个AIVAIC为Block0和Block1。其中Block0与Queue0、Queue1、Queue2、Queue3、Queue4进行通信Block1与Queue 5、Queue 6、Queue 7、Queue 8、Queue9进行通信。每一个消息队列对应一个AIV消息队列的深度固定为4即一次性最多可以容纳4个消息。CubeResGroupHandle2的消息队列个数为12表明有12个AIV。CubeResGroupHandle的消息处理顺序如CubeResGroupHandle2中黑色箭头所示。图 1基于CubeResGroupHandle的AI Core计算资源分组通信示意图![](https://raw.gitcode.com/cann/asc-devkit/raw/68eb55191616e7a7b08961a5c82a706272353b5f/docs/api/figures/基于CubeResGroupHandle的AI-Core计算资源分组通信示意图.png 基于CubeResGroupHandle的AI-Core计算资源分组通信示意图?utm_sourcegitcode_repo_files)基于CubeResGroupHandle实现AI Core计算资源分组步骤如下创建AIC上所需要的计算对象类型。创建通信区域描述KfcWorkspace用于记录通信消息Msg的地址分配。自定义消息结构体用于通信。自定义回调计算结构体根据实际业务场景实现Init函数和Call函数。创建CubeResGroupHandle。绑定AIV到CubeResGroupHandle。收发消息。AIV退出消息队列。创建AIC上所需要的计算对象类型。用户根据实际需求自定义AIC所需要的计算对象类型或者高阶API已提供的Matmul类型。例如创建Matmul类型如下其中A_TYPE、B_TYPE、 C_TYPE、BIAS_TYPE、CFG_NORM等含义请参考Matmul模板参数。// A_TYPE, B_TYPE, C_TYPE, BIAS_TYPE, CFG_NORM根据实际需求场景构造 using MatmulApiType MatmulImplA_TYPE, B_TYPE, C_TYPE, C_TYPE, CFG_NORM;创建KfcWorkspace。使用KfcWorkspace管理不同CubeResGrouphandle的消息通信区的划分。// 创建KfcWorkspace对象前需要对该workspaceGM清零 KfcWorkspace desc(workspaceGM);自定义消息结构体。用户需要自行构造消息结构体CubeMsgBody用于AIV向AIC发送通信消息。构造的CubeMsgBody必须64字节对齐该结构体最前面需要定义2字节的CubeGroupMsgHead使消息收发机制正常运行CubeGroupMsgHead结构定义请参考表2。除2字节的CubeGroupMsgHead外其余参数根据业务需求自行构造。表 1CubeMsgBody消息结构体参数名称含义CubeMsgBody用户自定义的消息结构体。结构体名称可自定义结构体大小需要64字节对齐。// 这里提供64B对齐的结构体示例用户实际使用时除CubeGroupMsgHead外其他参数个数及参数类型可自行构造 struct CubeMsgBody { CubeGroupMsgHead head; // 2B需放在结构体最前面, 自定义的CubeMsgBody中CubeGroupMsgHead的变量名需设置为head否则会编译报错。 uint8_t funcID; uint8_t skipCnt; uint32_t value; bool isTransA; bool isTransB; bool isAtomic; bool isLast; int32_t tailM; int32_t tailN; int32_t tailK; uint64_t aAddr; uint64_t bAddr; uint64_t cAddr; uint64_t aGap; uint64_t bGap; }表 2CubeGroupMsgHead结构体参数定义参数名称含义msgState表明该位置的消息状态。参数取值如下CubeMsgState::FREE表明该位置还未填写消息可执行AllocMessage。CubeMsgState::VALID表明该位置已经含有AIV发送的消息待AIC接收执行。CubeMsgState::QUIT表明该位置的消息为通知AIC有AIV将退出流程。CubeMsgState::FAKE表明该位置的消息为假消息。在消息合并场景被跳过处理任务的AIV需要发送假消息消息合并场景请参考PostFakeMsg中的介绍。aivID发送消息的AIV的序号。自定义回调计算结构体根据实际业务场景实现Init函数和Call函数。templateclass MatmulApiCfg, class CubeMsgBody struct NormalCallbackFuncs { __aicore__ inline static void Call(MatmulApiCfg mm, __gm__ CubeMsgBody *rcvMsg, CubeResGroupHandleCubeMsgBody handle){ // 用户自行实现逻辑 }; __aicore__ inline static void Init(NormalCallbackFuncsMatmulApiCfg, CubeMsgBody foo, MatmulApiCfg mm, GM_ADDR tilingGM){ // 用户自行实现逻辑 }; };计算逻辑结构体的模板参数请参考表3。表 3模板参数说明参数说明MatmulApiCfg用户自定义的AIC上计算所需要对象的数据类型参考步骤1该模板参数必须填入。CubeMsgBody用户自定义的消息结构体该模板参数必须填入。用户自定义回调计算结构体中需要包含固定的Init函数和Call函数函数原型如下所示。其中Init函数的参数说明请参考表4Call函数的参数说明请参考表5。// 该函数的参数和名称为固定格式函数实现根据业务逻辑自行实现。 __aicore__ inline static void Init(MyCallbackFuncMatmulApiCfg, CubeMsgBody myCallBack, MatmulApiCfg mm, GM_ADDR tilingGM){ // 用户自行实现内部逻辑 }表 4Init函数参数说明参数输入/输出说明myCallBack输入用户自定义的带模板参数的回调计算结构体。mm输入AIC上计算对象多为Matmul对象。tilingGM输入用户传入的tiling指针。// 该函数的参数和名称为固定格式函数实现根据业务逻辑自行实现。 __aicore__ inline static void Call(MatmulApiCfg mm, __gm__ CubeMsgBody *rcvMsg, CubeResGroupHandleCubeMsgBody handle){ // 用户自行实现内部逻辑 }表 5Call函数参数说明参数输入/输出说明mm输入AIC上计算对象多为Matmul对象。rcvMsg输入用户自定义的消息结构体指针。handle输入分组管理Handle用户调用其接口进行收发消息释放消息等。某算子的回调计算结构体的代码示例如下。// 用户自定义的回调计算逻辑 templateclass MatmulApiCfg, typename CubeMsgBody struct MyCallbackFunc { templateint32_t funcId __aicore__ inline static typename IsEqualfuncId, 0::Type CubeGroupCallBack(MatmulApiCfg mm, __gm__ CubeMsgBody *rcvMsg, CubeResGroupHandleCubeMsgBody handle) { GlobalTensorint64_t msgGlobal; msgGlobal.SetGlobalBuffer(reinterpret_cast__gm__ int64_t * (rcvMsg) sizeof(int64_t)); DataCacheCleanAndInvalidint64_t, CacheLine::SINGLE_CACHE_LINE, DcciDst::CACHELINE_OUT (msgGlobal); using SrcAT typename MatmulApiCfg::AType::T; auto skipNum 0; for (int i 0; i skipNum 1; i) { auto tmpId handle.FreeMessage(rcvMsg i); // msgPtr process is complete } handle.SetSkipMsg(skipNum); } templateint32_t funcId __aicore__ inline static typename IsEqualfuncId, 1::Type CubeGroupCallBack(MatmulApiCfg mm, __gm__ CubeMsgBody *rcvMsg, CubeResGroupHandleCubeMsgBody handle) { GlobalTensorint64_t msgGlobal; msgGlobal.SetGlobalBuffer(reinterpret_cast__gm__ int64_t * (rcvMsg) sizeof(int64_t)); DataCacheCleanAndInvalidint64_t, CacheLine::SINGLE_CACHE_LINE, DcciDst::CACHELINE_OUT (msgGlobal); using SrcAT typename MatmulApiCfg::AType::T; LocalTensorSrcAT tensor_temp; auto skipNum 3; auto tmpId handle.FreeMessage(rcvMsg, CubeMsgState::VALID); for (int i 1; i skipNum 1; i) { auto tmpId handle.FreeMessage(rcvMsg i, CubeMsgState::FAKE); } handle.SetSkipMsg(skipNum); // notify the cube not to process } __aicore__ inline static void Call(MatmulApiCfg mm, __gm__ CubeMsgBody *rcvMsg, CubeResGroupHandleCubeMsgBody handle) { if (rcvMsg-funcId 0) { CubeGroupCallBack0 (mm, rcvMsg, handle); } else if(rcvMsg-funcId 1) { CubeGroupCallBack1 (mm, rcvMsg, handle); } } __aicore__ inline static void Init(MyCallbackFuncMatmulApiCfg, CubeMsgBody foo, MatmulApiCfg mm, GM_ADDR tilingGM) { auto tempTilingGM (__gm__ uint32_t*)tilingGM; auto tempTiling (uint32_t*)(foo.tiling); for (int i 0; i sizeof(TCubeTiling) / sizeof(int32_t); i, tempTilingGM, tempTiling) { *tempTiling *tempTilingGM; } mm.SetSubBlockIdx(0); mm.Init(foo.tiling, GetTPipePtr()); } TCubeTiling tiling; };创建CubeResGroupHandle。用户使用CreateCubeResGroup接口创建一个或多个CubeResGroupHandle。/* * groupID为用户自定义的CreateCubeResGroup的groupID * MatmulApiType为定义好的AIC上计算对象的类型 * MyCallbackFunc为定义好的自定义回调计算结构体 * CubeMsgBody为自定义消息结构体 * desc为用户初始化好的通信区域描述 * groupID为1blockStart为0blockSize为12msgQueueSize为48tilingGm为指针存储了用户在AIC上所需要的tiling信息 */ auto handle AscendC::CreateCubeResGroupgroupID, MatmulApiType, MyCallbackFunc, CubeMsgBody(desc, 0, 12, 48, tilingGM);绑定AIV到CubeResGroupHandle。绑定AIV和消息队列序号。注意消息队列序号queIdx小于该CubeGroupHandle的消息队列总数每个AIV需要传入不同的queIdx。handle为步骤5中CreateCubeResGroup创建的CubeResGroupHandle对象。handle.AssignQueue(queIdx);AIV发消息。用户调用AllocMessage, PostMessage等接口进行消息的收发。其中调用AllocMessage获取消息结构体指针通过PostMessage发送消息在消息合并场景调用PostFakeMessage发送假消息示例如下。CubeGroupMsgHead head {CubeMsgState::VALID, (uint8_t)queIdx}; CubeMsgBody aCubeMsgBody {head, 0, 0, 0, false, false, false, false, 0, 0, 0, 0, 0, 0, 0, 0}; CubeMsgBody bCubeMsgBody {head, 1, 0, 0, false, false, false, false, 0, 0, 0, 0, 0, 0, 0, 0}; auto offset 0; if (GetBlockIdx() 0) { auto msgPtr handle.template AllocMessage(); // alloc for queue space offset handle.template PostMessage(msgPtr, bCubeMsgBody); // post true msgPtr bool waitState handle.template Waittrue (offset); // wait until the msgPtr is processed } else if (GetBlockIdx() 4) { auto msgPtr handle.AllocMessage(); offset handle.PostFakeMsg(msgPtr); // post fake msgPtr bool waitState handle.template Waittrue (offset); // wait until the msgPtr is processed } else { auto msgPtr handle.template AllocMessage(); offset handle.template PostMessage(msgPtr, aCubeMsgBody); bool waitState handle.template Waittrue (offset); // wait until the msgPtr is processed }AIV退出消息队列。调用AllocMessage获取消息结构体指针后通过SendQuitMsg发送当前消息队列退出。auto msgPtr handle.AllocMessage(); // 获取消息空间指针msgPtr handle.SetQuit(msgPtr); // 发送退出消息创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考