资讯动态

asc-devkit 中 TSCM 输入的 Matmul:L1 Buffer 自定义数据管理下的矩阵乘实现

发布时间:2026/10/17 10:15:40 来源:尧图企业网站定制
人工智能深度学习算子库CANNAscend【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址https://gitcode.com/cann/asc-devkit点击查看免费下载导读在 CANN asc-devkit 提供的昇腾算子开发语言Ascend C中Matmul 高阶 API 默认由框架自动完成「Global MemoryGM→ L1 Buffer → L0A/L0B → Cube」的数据搬入流程。而当开发者需要自行掌控矩阵数据在 L1 Buffer 中的摆放与生命周期时可以使用TSCMTemp Swap Cache Memory输入的 Matmul特性由开发者把 A、B 甚至 Bias 矩阵完整地搬入并驻留在 TSCM即 L1 Buffer 对应的逻辑内存中再通过SetTensorA/SetTensorB将 TSCM 地址直接交给 Matmul 计算。读完本文你将掌握 TSCM 的逻辑内存含义、适用场景与硬性约束、完整的调用代码范式以及配套的 Tiling 配置和可运行的仓库样例能够在算子开发中自主实现自定义搬入 跨 Matmul 对象的全局 Double Buffer这类高阶调度。TSCM 是什么L1 Buffer 的逻辑内存视图在 AI Core 硬件中L1 Buffer 是位于 Global Memory 与 L0A/L0B Buffer 之间的通用内部存储用于暂存 Cube 计算单元需要反复使用的数据以减少从总线读写的次数。硬件存储单元与搬运单元的详细介绍见基本架构。TSCM 表示 L1 Buffer 空间对应的逻辑内存。同一个物理内存可能对应多个不同的 TPosition例如 L1 Buffer 同时映射到 A1、B1、C1 和 TSCM 四个逻辑位置具体语义取决于当前所服务的计算流程左矩阵暂存、右矩阵暂存或共享通信详见数据通路。从数据结构看TSCM 是队列机制在目的地址为 TSCM Position 时的别名与 TQue、TQueBind 属于同一类型结构定义于 TSCM 简介template TPosition pos, int32_t depth, auto mask 0 using TSCM TQueBindpos, TPosition::TSCM, depth, mask;其中模板参数含义pos队列逻辑位置可以为VECIN、GM表示 TSCM 数据的来源方向depth队列深度表示队列可连续入队/出队的次数。队列深度为 1 时编译器有特殊优化推荐设置为 1mask比特位或TQueConfig配置控制 VECTOR0 与 VECTOR1 映射到 Cube 上的内存位置是否错开等TSCM 支持AllocTensor/EnQue/DeQue/FreeTensor接口且必须严格按照AllocTensor → EnQue → DeQue → FreeTensor的顺序配对使用完整生命周期管理不支持VacantInQue、HasTensorInQue等查询类接口。功能与使用场景功能介绍开发者可以自行管理 TSCM 以高效利用硬件资源。例如缓存一份 TSCM 数据在不同使用场景中灵活配置为 Matmul 操作的 A 矩阵、B 矩阵或 Bias 偏置矩阵实现内存复用与计算效率优化。在 TSCM 输入场景下用户管理整块 TSCM 内存空间Matmul 直接使用传入的 TSCM 内存地址不进行 Global Memory 到 TSCM 的数据搬入搬入动作由开发者自己完成。使用场景需要自定义数据搬入到 TSCM 及自定义管理的场景即需要自定义实现数据搬入功能例如非连续搬入对搬入数据进行预处理如格式转换、填充、量化等。用户通过自定义管理 TSCM可以灵活配置 MTE2 流水GM → L1 Buffer 方向的搬运单元参见搬运单元实现跨 Matmul 对象的全局 Double Buffer。Double Buffer 的核心思想是利用 MTE 指令队列与计算指令队列的独立性让数据搬运与计算并行执行以隐藏搬运时间详见 Double Buffer。约束说明TSCM 输入必须全载设置为 TSCM 输入的矩阵必须在 TSCM 中全载。所谓全载即全部的矩阵数据同时搬入并保持在 TSCM 中而不是像默认 GM 输入那样按迭代分块搬入。这一点也体现在 SetTensorA 的约束中若设置 TSCM 首地址默认矩阵可全载、已经位于 TSCMIterate 接口无需再进行 GM → L1 BufferA1/B1搬运。因此TSCM 的 Buffer 大小必须一次性覆盖单核参与计算所需的完整矩阵数据量例如 A 矩阵需要申请M * K * sizeof(元素类型)字节的空间见下文代码。核心调用流程与代码范式TSCM 输入 Matmul 的调用流程可概括为五步申请 TSCM Buffer → 自定义搬运 → 入队/出队 → 设置矩阵输入 → 迭代计算 → 释放 Buffer。以下为文档中的核心调用示例A 矩阵使用 TSCM 输入B 矩阵与 Bias 使用 GM 输入TQueTPosition::A1, 1 scm; // 队列逻辑位置A1队列深度为1 pipe-InitBuffer(scm, 1, tiling.M * tiling.Ka * sizeof(A_T)); // A_TYPE的TPosition为TSCMB_TYPE的TPosition为GM MatmulA_TYPE, B_TYPE, C_TYPE, BIAS_TYPE mm1; REGIST_MATMUL_OBJ(pipe, GetSysWorkSpacePtr(), mm1); mm1.Init(tiling); // 自定义A矩阵GM到TSCM的搬运 auto scmTensor scm.AllocTensorA_T(); DataCopy(scmTensor, gm_a, tiling.M * tiling.Ka); scm.EnQue(scmTensor); LocalTensorA_T scmLocal scm.DeQueA_T(); // A矩阵设置为TSCM输入B矩阵为GM输入 mm1.SetTensorA(scmLocal); mm1.SetTensorB(gm_b); mm1.SetBias(gm_bias); mm1.IterateAll(gm_c); scm.FreeTensor(scmLocal);对每一步骤逐一说明申请并初始化 TSCM BufferTQueTPosition::A1, 1 scm声明队列pipe-InitBuffer(scm, 1, tiling.M * tiling.Ka * sizeof(A_T))申请深度为 1、大小为整块 A 矩阵数据量M × Ka 个元素的 TSCM Buffer。队列深度 1 满足单次全载、一次性消费的语义编译器对该场景有专门优化。创建并注册 Matmul 对象MatmulA_TYPE, B_TYPE, C_TYPE, BIAS_TYPE mm1创建对象其中A_TYPE的 TPosition 必须为TSCMREGIST_MATMUL_OBJ(pipe, GetSysWorkSpacePtr(), mm1)完成对象初始化注册mm1.Init(tiling)传入 Tiling 参数。自定义数据搬入scm.AllocTensorA_T()从队列分配 tensorDataCopy(scmTensor, gm_a, tiling.M * tiling.Ka)将 GM 中的 A 矩阵连续搬入 TSCM。此处的 DataCopy 可以由任意自定义搬运逻辑含预处理替代这正是本特性的价值所在。入队/出队完成同步scm.EnQue(scmTensor)在搬运完成后将 tensor 入队scm.DeQueA_T()取出用于计算EnQue/DeQue 之间隐含了搬运完成与计算开始的同步语义对应 MTE2 与 Cube 流水之间的事件同步。设置输入并计算mm1.SetTensorA(scmLocal)将 TSCM 地址作为 A 矩阵输入SetTensorB(gm_b)、SetBias(gm_bias)分别设置 GM 来源的 B 矩阵与 Biasmm1.IterateAll(gm_c)完成单核全量计算并输出到 GM。释放 Buffer计算完成后scm.FreeTensor(scmLocal)归还 Buffer供下一次搬入复用。模板参数与 Tiling 侧的配套配置TSCM 输入不仅要在核函数Kernel侧设置还必须保证核函数侧、模板参数侧、Tiling 侧三方配置一致。MatmulType 模板参数创建 Matmul 对象时A、B、C、Bias 的类型信息通过MatmulType定义包括内存逻辑位置、数据格式、数据类型、是否转置、数据排布和是否开启 L1 复用参见 Matmul 模板参数与 Matmul 使用说明。TSCM 场景下关键参数MatmulType 参数TSCM 输入的要求POSITIONA 矩阵 / B 矩阵可设置为TPosition::TSCMAscend 950PR950DT 系列还支持 Bias 设置为 TSCMFORMAT输入矩阵设置为 TSCM 时对应 Format仅支持CubeFormat::NZ以 Ascend 950PR950DT 系列为例SRCPOSITIONA/B 矩阵 POSITION 配置为 TSCM 时必须设置 TSCM 中矩阵数据的来源逻辑位置默认为TPosition::GM也可为VECOUT在仓库样例中A 矩阵的完整类型声明为AscendC::MatmulTypeAscendC::TPosition::TSCM, CubeFormat::NZ, ATypeTiling 侧 SetAType 配置Tiling 侧通过SetAType设置 A 矩阵的位置、数据格式、数据类型、是否转置等信息这些信息必须和核函数Kernel侧的设置保持一致参见 SetAType。样例中的 Tiling 配置为tilingApi.SetAType( matmul_tiling::TPosition::TSCM, matmul_tiling::CubeFormat::NZ, matmul_tiling::DataType::DT_FLOAT16, IS_TRANS_A); tilingApi.SetBType( matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16, IS_TRANS_B); tilingApi.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); tilingApi.SetBiasType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT);即 A 矩阵位置为TSCM、格式为NZ、类型为float16B 矩阵与 Bias 均为 GM ND。转置一致性要求若 A 矩阵MatmulType的ISTRANS参数设置为falseSetTensorA的isTransposeA只能为false若强行设置为true精度会有异常。对于非 half、非 bfloat16_t 输入类型为确保 Tiling 侧与核函数侧 L1 Buffer 空间计算大小保持一致及结果精度正确核函数侧ISTRANS、SetTensorA的isTransposeA、Tiling 侧SetAType的isTrans三个参数必须同时为 true 或同时为 false详见 SetTensorA。仓库完整样例编译、运行与结果验证asc-devkit 仓库提供了与本文场景完全对应的完整算子样例matmul_tscm自定义数据来源为 GM 的 TSCM 输入的 Matmul 算子样例位于 examples/01_simd_cpp_api/04_advanced_api/00_matmul/matmul_tscm。样例组成如下matmul_tscm.asc核函数与 Host 侧主程序data_utils.h二进制数据读写工具CMakeLists.txt编译配置scripts/gen_data.py与scripts/verify_result.py测试数据生成与结果校验脚本。样例支持的硬件与软件版本产品CANN 软件版本Ascend 950PR 950DT 系列产品 CANN 9.1.0Atlas A3 系列产品 CANN 9.0.0Atlas A2 系列产品 CANN 9.0.0编译与运行步骤在样例根目录下执行source ${install_path}/cann/set_env.sh # 配置CANN环境变量install_path为CANN包安装目录默认 /usr/local/Ascend mkdir -p build cd build cmake -DCMAKE_ASC_ARCHITECTURESdav-2201 ..; make -j; # 编译工程默认npu模式 python3 ../scripts/gen_data.py # 生成测试输入数据 ./demo # 执行编译生成的可执行程序 python3 ../scripts/verify_result.py output/output.bin output/golden.bin # 验证输出结果编译选项说明选项可选值说明CMAKE_ASC_RUN_MODEnpu默认、cpu、sim运行模式NPU 运行、CPU 调试、NPU 仿真CMAKE_ASC_ARCHITECTURESdav-2201默认、dav-3510NPU 架构dav-2201 对应 Atlas A2/A3 系列dav-3510 对应 Ascend 950PR 950DT 系列使用 CPU 调试或 NPU 仿真模式时添加-DCMAKE_ASC_RUN_MODEcpu或-DCMAKE_ASC_RUN_MODEsim参数例如cmake -DCMAKE_ASC_RUN_MODEcpu -DCMAKE_ASC_ARCHITECTURESdav-2201 ..; make -j; # cpu调试模式 cmake -DCMAKE_ASC_RUN_MODEsim -DCMAKE_ASC_ARCHITECTURESdav-2201 ..; make -j; # NPU仿真模式注意切换编译模式前需清理 cmake 缓存可在 build 目录下删除CMakeCache.txt后重新 cmake。执行结果输出test pass!表示精度对比成功。CANN 环境安装方式可参考 quick_start。样例代码中的 TSCM 使用要点样例核函数MatmulKernel::Process中完整呈现了自定义搬入 TSCM 输入的实现matmul_tscm.asc// Copy aMatrix from gm to tscm AscendC::TSCMAscendC::TPosition::GM, 1 scm; pipe-InitBuffer(scm, 1, tiling.M * tiling.Ka * sizeof(AType)); auto scmTensor scm.AllocTensorAType(); DataCopy(scmTensor, aGlobal, tiling.M * tiling.Ka); scm.EnQue(scmTensor); AscendC::LocalTensorAType scmLocal scm.DeQueAType(); matmulObj.SetTensorA(scmLocal, IS_TRANS_A); matmulObj.SetTensorB(bGlobal, IS_TRANS_B); if (tiling.isBias) { matmulObj.SetBias(biasGlobal); } matmulObj.IterateAll(cGlobal); matmulObj.End(); scm.FreeTensor(scmLocal);与文档示例略有差异的是样例使用TSCMTPosition::GM, 1声明队列来源为 GMBuffer 大小按整块 A 矩阵M * Ka元素全载申请并在尾块场景通过matmulObj.SetTail(tailM, tailN)处理多核切分的非对齐边界。样例同时给出了多核切分的偏移计算方式CalcOffset按 M 方向优先切分 core 索引与 Host 侧 Tiling 生成、ACL 内存申请、kernel launch 的完整流程可作为自研算子的直接模板。底层数据通路与设计要点TSCM 输入在数据流中的位置默认 Matmul 的 Cube 计算数据流为GM → L1 → L0A/L0B → Cube → L0C → FixPipe → GM。TSCM 输入场景下GM → L1TSCM这一段由开发者通过DataCopyMTE2 流水自行完成Matmul 只负责TSCML1→ L0A/L0B → Cube → L0C → GM的后续环节。同时需要注意NPU 架构版本 3510Ascend 950PR 950DT删除了 GM 到 L0A/L0B 的直接数据通路L1 Buffer 成为矩阵计算输入的必经中转TSCM 管理的价值在该架构上更为突出详见数据通路。TSCM Buffer 数量与资源限制由于 TSCM 分配的 Buffer 中存储着同步事件 eventID且该结构与 Cube 类高阶 APIMatmul 高阶 API、宏函数调用方式共同使用因此同一个 TPosition 上 TSCM Buffer 的数量与硬件的同步事件 eventID 以及 Matmul 对象数量有关。具体限制如下见 TSCM 简介L1 BufferTSCM从 Unified BufferUBVECIN发起的 Buffer 块数量与 Matmul 对象数量之和最大为 10 个不允许申请的 TSCM Buffer 超出规格限制超出规格可能引起未定义行为从 UB 发起的 L1 BufferTSCM队列内部实现会占用核间同步 flagId若与CrossCoreSetFlag/CrossCoreWaitFlag同时使用需注意避免 flagId 冲突。生命周期与内存复用建议TSCM 队列的AllocTensor → EnQue → DeQue → FreeTensor必须严格配对执行EnQue返回 false 表示队列已满、入队失败见 EnQueDeQue返回队列中取出的 LocalTensor见 DeQue。推荐队列深度为 1深度为 1 时编译器有特殊优化性能通常更好。开发者可缓存一份 TSCM 数据在不同使用场景中灵活配置为 A 矩阵、B 矩阵或 Bias 矩阵实现内存复用配合自定义 MTE2 搬运节奏可以实现跨 Matmul 对象的全局 Double Buffer将数据搬运时间隐藏在计算流水之后。小结TSCM 输入的 Matmul 是 Ascend C 中内存管理下放给开发者的关键特性它以 TSCM 逻辑位置封装 L1 Buffer让矩阵数据在进入 Cube 之前完全处于开发者的掌控之下。使用时需要把握三个核心点矩阵必须在 TSCM 全载Buffer 大小按整块数据申请、核函数侧/Tiling 侧配置严格一致POSITIONTSCM、FormatNZ、isTrans 对齐、队列生命周期严格配对AllocTensor → EnQue → DeQue → FreeTensor。在此基础上开发者即可自由实现非连续搬入、数据预处理以及跨 Matmul 对象的全局 Double Buffer 等高阶调度相关完整范式可直接参考仓库中的 matmul_tscm 样例。赞分享人工智能深度学习算子库CANNAscend【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址https://gitcode.com/cann/asc-devkit点击查看免费下载相关推荐Ascend C 算子开发Matmul VECOUT 输入直调实战——基于 asc-devkit 自主管理 Unified Buffer 的矩阵乘样例解析Ascend C 算子开发Matmul VECOUT 输入直调实战——基于 asc devkit 自主管理 Unified Buffer 的矩阵乘样例解析 本人工智能深度学习算子库CANNAscendasc-devkit Matmul 自定义 TSCM 输入直调样例详解从 L1 Buffer 自主管理到编译运行全流程asc devkit Matmul 自定义 TSCM 输入直调样例详解从 L1 Buffer 自主管理到编译运行全流程 本篇文章围绕 asc devkitC人工智能深度学习算子库CANNAscendasc-devkit ND_ALIGN 格式矩阵乘输出实战Matmul API 实现 N 方向 32 字节对齐的 C 矩阵输出asc devkit ND_ALIGN 格式矩阵乘输出实战Matmul API 实现 N 方向 32 字节对齐的 C 矩阵输出 本文基于 asc devkit人工智能深度学习算子库CANNAscend上一篇终极指南Insomnia模块化架构与扩展机制深度解析下一篇Monad BFT监控与日志分析运维人员必备指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑