CANN/asc-devkit TSCM简介

CANN/asc-devkit TSCM简介
TSCM简介Vector和Cube之间通过队列Queue完成任务间通信和同步。TSCM是数据通路的目的地在TSCM Position时用来管理执行队列相关操作、相关资源的数据结构。TSCM与TQueBindTQue属于相同类型结构。TSCM定义如下template TPosition pos, int32_t depth, auto mask 0 using TSCM TQueBindpos, TPosition::TSCM, depth, mask;表 1模板参数介绍参数名称含义pos队列逻辑位置可以为VECIN、GM。关于TPosition的具体介绍请参考TPosition。depth队列的深度表示该队列可以连续进行入队/出队的次数在代码运行时对同一个队列有n次连续的EnQue中间没有DeQue那么该队列的深度就需要设置为n。注意这里的队列深度和double buffer无关队列机制用于实现流水线并行double buffer在此基础上进一步提高流水线的利用率。即使队列的深度为1仍可以开启double buffer。队列的深度设置为1时编译器对这种场景做了特殊优化性能通常更好推荐设置为1。如下样例中队列没有连续入队队列的深度设置为1。a1 que.AllocTensor(); que.EnQue(a1); a1 que.DeQue(); que.FreeTensor(a1);如下样例中队列连续2次入队队列的深度应设置为2仅在极少数preload场景比如连续搬入两份数据计算处理一份完成后再搬入一份然后计算处理提前搬入的一份...可能会使用。其他情况下均不推荐depth 2 。a1 que.AllocTensor(); a2 que.AllocTensor(); que.EnQue(a1); que.EnQue(a2); a1 que.DeQue(); a2 que.DeQue(); que.FreeTensor(a1); que.FreeTensor(a2);maskmask是int类型时采用比特位表达信息bit 0位为预留参数。bit 1位为预留参数。bit 2位为0时VECTOR0与VECTOR1映射到CUBE上的内存位置错开为1时VECTOR0与VECTOR1映射到CUBE上的内存位置相同。mask是const TQueConfig*类型时TQueConfig结构定义和参数说明如下。struct TQueConfig { bool nd2nz false; // 不支持默认为false bool nz2nd false; // 不支持默认为false bool scmBlockGroup false; // tscm相关参数为falseVECTOR0与VECTOR1映射到CUBE上的内存位置错开为true时VECTOR0与VECTOR1映射到CUBE上的内存位置相同。 uint32_t bufferLen 0; // 与InitBuffer时输入的len参数保持一致可以在编译期做性能优化传0表示在InitBuffer时做资源分配。 uint32_t bufferNumber 0; // 与InitBuffer时输入的num参数保持一致可以在编译期做性能优化传0表示在InitBuffer时做资源分配。 uint32_t consumerSize 0; // 预留参数 TPosition consumer[8] {}; // 预留参数 bool enableStaticEvtId false; // 预留参数 bool enableLoopQueue false; // 预留参数 };[!NOTE]说明TSCM通过using定义TSCM为TQueBind目的地址为TSCM Position时的别名。支持AllocTensor/EnQue/DeQue/FreeTensor接口。必须严格按照AllocTensor-EnQue-DeQue-FreeTensor的操作执行完整的生命周期且配对使用。但TSCM并不需要支持TQueBind的所有接口。不支持VacantInQue/HasTensorInQue/GetTensorCountInQue/HasIdleBuffer。由于TSCM分配的Buffer中存储着同步事件eventID且该结构伴随着与Cube类高阶API如Matmul高阶API宏函数调用方式)共同使用故同一个TPosition上TSCM Buffer的数量与硬件的同步事件eventID以及Matmul对象数量有关。TSCM从VECIN发起的Buffer块数量与Matmul对象数量之和最大为10个。不允许申请的TSCM Buffer超出规格限制超出规格可能会引起未定义行为。如下是一个简单的使用示例TSCMTPosition::VECIN, 1 tscm; for () { auto scmTensor tscm.AllocTensorfloat(); // 在搬运数据从UB-TSCM前分配Buffer DataCopy(scmTensor, ubLocal, 1024); // 将UB数据搬运至TSCM准备用于Matmul计算 tscm.EnQue(scmTensor); //搬运完成在Matmul计算前EnQue/DeQue LocalTensorfloat scmLocal tscm.DeQuefloat(); mm.SetTensorA(scmLocal); mm.SetTensorB(gm_b); mm.IterateAll(gm_c); tscm.FreeTensor(scmLocal); // Matmul计算完成后释放tensor }与高阶API Matmul配合使用调用示例如下{ typedef matmul::MatmulTypeAscendC::TPosition::TSCM, CubeFormat::NZ, half, true, LayoutMode::NONE, false, AscendC::TPosition::VECIN A_TYPE; typedef matmul::MatmulTypeAscendC::TPosition::GM, CubeFormat::ND, half B_TYPE; typedef matmul::MatmulTypeAscendC::TPosition::GM, CubeFormat::ND, float C_TYPE; typedef matmul::MatmulTypeAscendC::TPosition::GM, CubeFormat::ND, float BIAS_TYPE; matmul::MatmulA_TYPE, B_TYPE, C_TYPE, BIAS_TYPE mm1; constexpr uint32_t M 32; constexpr uint32_t N 32; constexpr uint32_t K 32; AscendC::GlobalTensorhalf aGlobal; AscendC::GlobalTensorhalf bGlobal; AscendC::GlobalTensorfloat cGlobal; AscendC::GlobalTensorfloat biasGlobal; aGlobal.SetGlobalBuffer(reinterpret_cast__gm__ half *(aGM), M * K); bGlobal.SetGlobalBuffer(reinterpret_cast__gm__ half *(bGM), K * N); cGlobal.SetGlobalBuffer(reinterpret_cast__gm__ float *(cGM), M * N); TCubeTiling tiling; AscendC::TPipe pipe; AscendC::TSCMAscendC::TPosition::VECIN, 1 scm; AscendC::TQueAscendC::TPosition::VECIN, 1 qIn; pipe.InitBuffer(scm, 1, M * K * sizeof(half)); pipe.InitBuffer(qIn, 1, M * K * sizeof(half)); REGIST_MATMUL_OBJ(pipe, workspaceGM, mm1, tiling); auto scmTensor scm.AllocTensorhalf(); auto ubTensor qIn.AllocTensorhalf(); AscendC::Nd2NzParams intriParams; DataCopy(ubTensor, aGlobal, M * K); qIn.EnQue(ubTensor); AscendC::LocalTensorhalf ubLocal qIn.DeQuehalf(); AscendC::DataCopy(scmTensor, ubLocal, intriParams); scm.EnQue(scmTensor); AscendC::LocalTensorhalf scmLocal scm.DeQuehalf(); mm1.SetTensorA(scmLocal); mm1.SetTensorB(bGlobal); mm1.IterateAll(cGlobal); scm.FreeTensor(scmLocal); qIn.FreeTensor(ubLocal); }创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考