Matmul 多核对齐切分完整指南:从切分策略到核数配置
【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit
CANN asc-devkit 面向昇腾 AI 处理器的算子开发,其 Matmul 高阶 API 提供了MultiCoreMatmulTiling这一多核矩阵乘 Tiling 对象,用于把大矩阵合理地分配到多个核上并行计算。这篇文章将带大家弄清多核对齐切分的两种策略、Tiling 参数的含义,以及SetDim与SetBlockDim的正确用法,最后给出可直接套用的代码模板。
为什么多核场景必须做矩阵切分
单核处理的性能瓶颈
一次完整的矩阵乘C(M,N) = A(M,K) × B(K,N)需要 M×N×K 量级的乘加运算。在单核上顺序执行时,核内存储空间有限、计算单元空闲率偏高,数据量一大就很容易成为整个算子的性能短板。因此,要提升计算效率,最直接的手段就是让多个核同时参与计算。
多核并行的核心思路
多核并行的前提,是把大矩阵切成若干独立的分块,每个核只处理属于自己的那部分数据。切分后的每个分块大小(即单核负载)会被记录到 Tiling 参数中,例如SingleCoreM、SingleCoreN、SingleCoreK。这些参数是设备侧 Kernel 拿到多少数据、按什么尺寸搬移和计算的依据,也是多核场景与单核场景在 Tiling 阶段的本质区别。
两种主流切分策略拆解
按照是否切分 K 轴,多核对齐切分分为两种策略。不同策略决定了分块在核间的分布方式,也直接影响累加逻辑的写法。
不切分 K 轴:沿 M、N 轴分块
这种策略只切 M、N 两个维度,K 维度保持完整,具体划分如下:
- A 矩阵:沿 M 轴切分,得到若干份大小为
SingleCoreM × K的分块; - B 矩阵:沿 N 轴切分,得到若干份大小为
K × SingleCoreN的分块; - C 矩阵:单核上由
SingleCoreM × K的 A 分块与K × SingleCoreN的 B 分块相乘,直接得到SingleCoreM × SingleCoreN的 C 分块。
举例来说,若有 8 个核参与计算,把 A 沿 M 轴切成 4 块、B 沿 N 轴切成 2 块,就得到 4×2 的核间网格。每个核只需要加载自己那一份 A 分块和 B 分块,例如某个核仅处理绿色标记的数据,其输出就是对应位置SingleCoreM × SingleCoreN的 C 分块。
切分 K 轴:M、N、K 三轴联合分块
当单核的存储放不下完整 K 维数据,或者希望进一步提高并行度时,可以对三个轴同时切分:
- A 矩阵:沿 M 轴切成
SingleCoreM,沿 K 轴切成SingleCoreK,单核处理SingleCoreM × SingleCoreK的数据; - B 矩阵:沿 K 轴切成
SingleCoreK,沿 N 轴切成SingleCoreN,单核处理SingleCoreK × SingleCoreN的数据; - C 矩阵:每个 C 分块不再由一次乘法得到,而是
A1×B1 + A2×B2 + A3×B3这样的累加结果。
以切分成 3 份 K 块为例,C 矩阵中的某个 R 块需要通过 A1×B1、A2×B2、A3×B3 三组乘积累加得到。这三组乘法互相独立,恰好可以分配到不同的核上并行执行,之后再把部分和累加回 C 分块。
两种策略如何选择
如果 K 维相对较小、单核放得下整段 K 数据,优先选择不切 K 轴的方案,累加逻辑简单、代码更易维护;如果 K 很大或核数很多、需要更大并行度,则选择三轴切分方案。需要留意的是,切 K 轴会引入跨核的部分和累加,通常需要额外的同步或归约处理。
关键参数与核数设置规则
Tiling 参数的含义
SingleCoreM、SingleCoreN、SingleCoreK是切分结果的直接体现,分别表示单核上处理的 M、N、K 维度尺寸。host 侧通过调用MultiCoreMatmulTiling的接口自动计算并获取这些参数,无需手动推算。它们会随算子的输入形状、可用核数自动调整,属于“声明形状后自动算好”的参数。
SetDim 与 SetBlockDim 的分工
多核 Tiling 中有一个容易混淆的点:SetDim与SetBlockDim各自负责什么。
- SetDim:设置 Matmul 计算可用的核数,仅在多核场景下使用,用于驱动 Tiling 参数的计算,即告诉 Tiling 对象“有多少核可以参与矩阵乘”;
- SetBlockDim:设置整个算子计算所用核数,即实际会被加载执行的核数,这个值是必须设置的,规则与
numBlocks的说明一致。
在纯 Cube 模式(只有矩阵计算)下,典型做法是先用SetDim把当前 AI 处理器上可用的 Cube 核数传入,再通过GetTiling得到 Matmul 实际使用的核数,该值会小于等于可用的核数。随后用户按实际使用的核数配置SetBlockDim。若算子还包含矢量计算(MIX 模式),核数设置规则会更复杂,需要参考 MIX 场景核数设置规则单独处理。
需要注意的约束
本场景没有额外限制条件,只要遵循上述设置顺序即可:先构造 Tiling 对象并设置维度与类型,再设置核数,最后获取 Tiling 参数。注意GetTiling的返回值用于判断是否成功,返回 -1 表示 Tiling 生成失败。
调用示例与关键步骤解读
以纯 Cube 模式的浮点矩阵乘为例,下面这段代码展示了多核 Tiling 的完整调用流程,可以分为三步理解。
第一步:构造多核 Tiling 对象
首先根据 SoC 版本获取平台实例,并以此构造MultiCoreMatmulTiling对象。与单核场景不同,多核必须使用该类而不是普通 Tiling 对象,否则无法获取多核相关的切分参数。
// 构造多核Tiling对象 auto ascendcPlatform = platform_ascendc::PlatformAscendCManager::GetInstance(socVersion); matmul_tiling::MultiCoreMatmulTiling cubeTiling(*ascendcPlatform); // 仅包含Cube计算的算子,设置可参与矩阵乘运算的核数为当前AI处理器上的Cube核数 cubeTiling.SetDim(ascendcPlatform.GetCoreNumAic());这里通过GetCoreNumAic()拿到当前 AI 处理器上的 Cube 核数并传给SetDim,相当于告诉 Tiling 对象“最多可以用这么多核”。
第二步:声明矩阵类型与形状
接着分别声明 A、B、C 三个矩阵以及偏置在全局内存中的位置、格式与数据类型,并传入原始的 M、N、K 形状。是否需要偏置由EnableBias控制。
cubeTiling.SetAType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); cubeTiling.SetBType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); cubeTiling.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); cubeTiling.SetBiasType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); cubeTiling.SetOrgShape(M, N, K); cubeTiling.SetShape(M, N, K); cubeTiling.EnableBias(isBias);第三步:获取 Tiling 参数
最后把结果写入TCubeTiling结构体,并检查返回值。拿到 tilingData 后,后续即可据此为设备侧 Kernel 计算地址偏移、循环边界等运行时信息。
optiling::TCubeTiling tilingData; // 获取Tiling参数 int ret = cubeTiling.GetTiling(tilingData); // if ret = -1, gen tiling failed小结
多核对齐切分的本质,是把大矩阵按 M、N、K 三个维度切分到多个核上并行计算。不切 K 轴时逻辑简单、适合 K 较小的场景;切 K 轴时并行度更高,但需要处理跨核的部分和累加。在实际编码中,牢记三点即可少走弯路:多核场景务必使用MultiCoreMatmulTiling;SetDim决定“最多可用多少核”,SetBlockDim决定“实际加载多少核”,后者必须设置;最后用GetTiling的返回值确认 Tiling 是否生成成功。
【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考