- 人工智能
- 深度学习
- 算子库
- CANN
- Ascend
【免费下载链接】asc-devkit
本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。
导读
SetShape是 Ascend C Matmul Tiling API 中用于设置 Matmul 计算形状(m、n、k)的核心接口,也是使用 MatmulApiTiling / MultiCoreMatmulTiling / BatchMatmulTiling 获取 Tiling 参数时必须调用的关键步骤之一。本文以开源仓库 asc-devkit 中该接口的官方文档为骨架,结合 Tiling 源码实现 与 单元测试用例,深入讲解 SetShape 的两种参数传入方式、与 SetOrgShape 的配合关系、"-1 回退"机制的底层原理,并给出单核、多核、BatchMatmul 三种场景的完整可运行示例。读完本文,你将能够正确配置 Matmul Tiling 的形状参数,并理解含脏数据的原始矩阵应如何通过 SetShape + SetOrgShape 组合完成 Tiling 计算。
功能说明:SetShape 设置什么
SetShape用于设置 Matmul 计算的形状 m、n、k,单位为元素个数。该形状既可以是原始完整矩阵的形状,也可以是原始矩阵的局部矩阵形状(例如只计算某个子块);该形状的矩阵乘可以由单核完成,也可以由多核切分后共同完成。
从 MatmulApiTilingBase 源码 可以看到,SetShape本质上写入的是singleM、singleN、singleK三个成员变量:
int32_t MatmulApiTilingBase::SetShape(int32_t m, int32_t n, int32_t k) { TILING_LOG_DEBUG("Set Single M: %d", m); TILING_LOG_DEBUG("Set Single N: %d", n); TILING_LOG_DEBUG("Set Single K: %d", k); this->singleM = m; this->singleN = n; this->singleK = k; if (this->orgM == -1 && this->orgN == -1 && this->orgKa == -1 && this->orgKb == -1) { this->orgM = m; this->orgN = n; this->orgKa = k; this->orgKb = k; } return 0; }注意上述源码中的一个重要细节:如果此前尚未调用SetOrgShape,SetShape会自动把 orgM、orgN、orgKa、orgKb 一并设置为 m、n、k。也就是说,在"完整矩阵、无脏数据"的最简单场景下,只调用SetShape即可同时完成"计算形状"与"原始形状"的设置。
参数传入的两种方式
使用本接口时,存在两种参数传入方式,这也是 SetShape 使用中最关键的区别点:
方式一:直接传入具体的 m、n、k
传入 Matmul 计算的完整形状 m、n、k,调用 GetTiling 接口时,Tiling 算法将直接按照 m、n、k 计算并返回 Tiling 参数。
tiling.SetShape(1024, 1024, 1024); // 设置Matmul计算的形状 tiling.SetOrgShape(1024, 1024, 1024);方式二:m、n、k 中任意一个或多个位置传入 -1
当 m、n、k 中任意一个或多个参数位置传入 -1 时,调用 GetTiling 接口时,该位置将回退取用 SetOrgShape 接口中设置的原始形状 M、N、K(或 Ka/Kb),然后由接口内部计算最优 Tiling 参数。
这一回退逻辑在 Tiling 算法源码中体现得非常直接,见 matmul_tiling_algorithm.cpp:
int32_t MatmulTilingAlgorithm::GetSingleM() const { return tilingIns_->singleM != -1 ? tilingIns_->singleM : tilingIns_->orgM; } int32_t MatmulTilingAlgorithm::GetSingleN() const { return tilingIns_->singleN != -1 ? tilingIns_->singleN : tilingIns_->orgN; } int32_t MatmulTilingAlgorithm::GetSingleK() const { return tilingIns_->singleK != -1 ? tilingIns_->singleK : tilingIns_->orgKa; }即:singleM不为 -1 时以 SetShape 传入值为准;为 -1 时自动使用 orgM;K 方向回退到 orgKa。最终 TilingData 中的 M、N、Ka、Kb 也直接来源于原始形状:
tilingIns_->tiling_.set_M(tilingIns_->orgM); tilingIns_->tiling_.set_N(tilingIns_->orgN); tilingIns_->tiling_.set_Ka(tilingIns_->orgKa); tilingIns_->tiling_.set_Kb(tilingIns_->orgKb);典型场景:K 方向含脏数据的原始矩阵
"-1 回退"最典型的应用场景是:原始 A 矩阵的 K 方向最后一列为不参与 Matmul 计算的脏数据。此时:
- 在 SetOrgShape 接口中设置包含该列数据的原始形状;
- 在
SetShape接口中设置 Matmul实际计算的 K 方向大小; - 同时将参数 m、n 设置为 -1,表示 M、N 方向按照原始形状 M、N 计算 Tiling。
这样,Tiling 计算在 M、N 方向使用原始完整形状,在 K 方向使用剔除脏数据后的实际计算大小,从而保证搬运与计算偏移的正确性。源码中的回退逻辑(singleM != -1 ? singleM : orgM)正是为这种"部分方向指定、部分方向回退"的组合而设计。
函数原型
int32_t SetShape(int32_t m, int32_t n, int32_t k)该接口为MatmulApiTilingBase基类的虚函数,由MatmulApiTiling、MultiCoreMatmulTiling、BatchMatmulTiling三个类继承/重写。多核类 MultiCoreMatmulTiling::SetShape 的实现比基类更谨慎:当参数为 -1 时不会用 -1 覆盖原始形状的对应维度:
int32_t MultiCoreMatmulTiling::SetShape(int32_t m, int32_t n, int32_t k) { this->singleM = m; this->singleN = n; this->singleK = k; if (this->orgM == -1 && this->orgN == -1 && this->orgKa == -1 && this->orgKb == -1) { this->orgM = m != -1 ? m : this->orgM; this->orgN = n != -1 ? n : this->orgN; this->orgKa = k != -1 ? k : this->orgKa; this->orgKb = k != -1 ? k : this->orgKb; } return 0; }也就是说,在多核场景下即使 m/n/k 传入 -1,原始形状也能保持由SetOrgShape设置的取值不被破坏。
参数说明
表1参数说明
| 参数名 | 输入/输出 | 描述 |
|---|---|---|
| m | 输入 | 设置 Matmul 计算的 M 方向大小,单位为元素。 |
| n | 输入 | 设置 Matmul 计算的 N 方向大小,单位为元素。 |
| k | 输入 | 设置 Matmul 计算的 K 方向大小,单位为元素。 |
三个参数均为int32_t类型。取值含义区分两种情形:
- 正值:作为该方向的实际计算大小参与 Tiling 计算;
- -1:不指定该方向,Tiling 计算时回退使用 SetOrgShape 中设置的原始形状对应维度(M→orgM,N→orgN,K→orgKa)。
返回值说明
- -1:设置失败;
- 0:设置成功。
需要注意的是,SetShape自身的返回值只代表形状参数是否被成功记录;真正的 Tiling 计算成功与否,取决于随后调用 GetTiling 的返回值(-1表示计算失败)。
约束说明
无。SetShape本身没有额外的参数约束;但 Tiling 计算的整体合法性(如singleM/singleN/singleK不能为 0、base 块不能超过 L0A/L0B/L0C 容量等)由 GetTiling 内部的CheckSetParam()统一校验,见 matmul_tiling_base.cpp。
与 SetOrgShape 的配合关系
SetShape与SetOrgShape是成对使用的两个接口,理解二者差异是正确使用的前提:
- SetShape:设置Matmul 实际计算的形状 singleM、singleN、singleK;
- SetOrgShape:设置原始完整的形状 orgM、orgN、orgKa、orgKb,主要用于辅助 Matmul API 搬运时的偏移计算。
典型组合一:形状一致(无脏数据)
auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); matmul_tiling::MatmulApiTiling tiling(ascendcPlatform); tiling.SetShape(1024, 1024, 1024); // 设置Matmul计算的形状 tiling.SetOrgShape(1024, 1024, 1024);典型组合二:K 方向剔除脏数据(SetShape 指定 K,m/n 传 -1)
假设原始 A 矩阵形状为 (1024, 1024),但 K 方向最后一列为脏数据,实际参与计算的 K 为 1023:
matmul_tiling::MatmulApiTiling tiling(ascendcPlatform); tiling.SetOrgShape(1024, 1024, 1024); // 原始完整形状,包含脏数据列 tiling.SetShape(-1, -1, 1023); // M、N 回退到原始形状,K 指定实际计算大小典型组合三:Ka、Kb 不等长(矩阵乘变形场景)
当原始矩阵 Ka 与 Kb 不相等时(例如分形或转置变形场景),需要使用 SetOrgShape 的四参数重载分别设置 orgKa 与 orgKb:
tiling.SetShape(1024, 1024, 1024); tiling.SetOrgShape(1024, 1024, 1024, 1280); // orgKa=1024,orgKb=1280参数 orgKaIn 和 orgKbIn 可以不相等,二者并不是实际 Matmul 计算时的 K,仅用于辅助 Matmul API 搬运时的偏移计算。
三种 Tiling 对象下的完整调用示例
根据 Matmul Tiling 类使用说明,使用流程为:先创建 Tiling 对象,再设置 A/B/C/Bias 类型与形状信息,最后调用 GetTiling 获取结果。SetShape在流程中位于"设置形状信息"步骤。
单核 Tiling(MatmulApiTiling)
auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); matmul_tiling::MatmulApiTiling tiling(ascendcPlatform); // 设置A、B、C、Bias矩阵Position、Format、DType信息 tiling.SetAType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); tiling.SetBType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); tiling.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); tiling.SetBiasType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); tiling.SetShape(1024, 1024, 1024); // 设置单核计算的M、N、K大小 tiling.SetOrgShape(1024, 1024, 1024); // 设置原始输入M、N、K大小,单核Tiling与SetShape一致 tiling.EnableBias(true); // 设置matmul计算包含bias tiling.SetBufferSpace(-1, -1, -1); // 设定允许使用的空间,缺省使用该AI处理器所有空间 optiling::TCubeTiling tilingData; int64_t ret = tiling.GetTiling(tilingData); // if ret = -1, get tiling failed多核 Tiling(MultiCoreMatmulTiling)
auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); matmul_tiling::MultiCoreMatmulTiling tiling(ascendcPlatform); tiling.SetDim(1); // 设置参与计算的核数为1 tiling.SetAType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); tiling.SetBType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); tiling.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); tiling.SetBiasType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); tiling.SetShape(1024, 1024, 1024); // 设置整体计算的M、N、K大小 tiling.SetSingleShape(1024, 1024, 1024);// 设置单核计算的形状 tiling.SetOrgShape(1024, 1024, 1024); tiling.EnableBias(true); tiling.SetBufferSpace(-1, -1, -1); optiling::TCubeTiling tilingData; int64_t ret = tiling.GetTiling(tilingData); // if ret = -1, get tiling failedBatchMatmul Tiling(BatchMatmulTiling)
auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); matmul_tiling::BatchMatmulTiling bmmTiling(ascendcPlatform); bmmTiling.SetAType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); bmmTiling.SetBType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); bmmTiling.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); bmmTiling.SetBiasType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); bmmTiling.EnableBias(true); bmmTiling.SetShape(64, 48, 32); bmmTiling.SetSingleShape(64, 48, 32); bmmTiling.SetOrgShape(64, 48, 32); // Layout类型为NORMAL时,通过SetBatchInfoForNormal设置A、B、C矩阵的Layout轴信息 bmmTiling.SetBatchInfoForNormal(2, 2, 64, 48, 32); bmmTiling.SetBatchNum(2); bmmTiling.SetBufferSpace(-1, -1, -1); optiling::TCubeTiling tilingData; int64_t ret = bmmTiling.GetTiling(tilingData); // if ret = -1, get tiling failed上述示例中,SetShape设置的形状与SetOrgShape完全一致(均为完整矩阵);在多核与 BatchMatmul 场景,还需要通过 SetSingleShape 显式指定单核形状(默认 -1 时由 Tiling 函数自行计算)。
头文件与依赖
- Matmul 单核 Tiling:
#include "lib/matmul/matmul_tiling.h"(对应仓库 include/adv_api/matmul/matmul_tiling.h); - Matmul 多核 Tiling / BatchMatmul Tiling:
#include "lib/matmul/bmm_tiling.h"(对应仓库 include/adv_api/matmul/bmm_tiling.h)。
Tiling 对象创建时,推荐使用带参构造函数MatmulApiTiling(const platform_ascendc::PlatformAscendC&),由硬件平台信息(AI Core 各存储单元大小等)驱动更优的 Tiling 计算,详细说明见 Matmul Tiling 类构造函数。
源码级验证:-1 参数在测试与实现中的实际行为
仓库 tests/api/adv_api/tiling/test_matmul_api_tiling.cpp 中的测试用例大量使用SetOrgShape + SetShape(-1, -1, -1)组合,验证了"-1 回退到原始形状"的机制,例如:
TEST_F(TestMatmulAPITiling, TestMatmulApiTilingMultiCoreBTSCM) { optiling::TCubeTiling tilingData; matmul_tiling::MultiCoreMatmulTiling tilingApi; tilingApi.SetDim(24); tilingApi.SetAType( matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); tilingApi.SetBType( matmul_tiling::TPosition::TSCM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); tilingApi.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::NZ, matmul_tiling::DataType::DT_FLOAT); tilingApi.SetBiasType( matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); tilingApi.SetOrgShape(65536, 64, 64); tilingApi.SetShape(-1, -1, -1); // 三个方向全部回退到原始形状 tilingApi.EnableBias(false); tilingApi.SetBufferSpace(-1, -1, -1); int64_t res = tilingApi.GetTiling(tilingData); EXPECT_EQ(res, 0); // Tiling计算成功 }这类用例证明:即使SetShape全传 -1,只要SetOrgShape提供了原始形状,GetTiling依然能够基于原始形状完成 Tiling 计算。此外,测试中还覆盖了SetShape(736, 7168, 4096)与SetOrgShape(736, 7168, 4096)完全一致的常规路径,并校验了多核切分后 singleCoreM / singleCoreN 的 16 元素对齐约束(对应 TCubeTiling 结构体 中对齐要求)。
常见问题与使用建议
- 先 SetShape 还是先 SetOrgShape?从基类实现看,若先调用
SetShape,则 org 形状会被自动填充为 m/n/k;若随后调用SetOrgShape,org 会被覆盖为显式设置值。因此当形状不一致(如剔除脏数据)时,务必先 SetOrgShape、再 SetShape(-1, -1, 实际K),确保回退使用的原始形状正确。 - -1 只能用于"回退到原始形状"的语义:不要混用 0 或负数作为"不设置"的标记,0 会被
CheckSetParam()判定为非法(singleM/N/K can not be zero),导致 GetTiling 返回 -1。 - Tiling 计算失败的排查:当 GetTiling 返回 -1 时,将日志级别设置为 WARNING 并搜索关键字 "MatmulApi Tiling" 可定位失败原因;计算成功时可将日志级别设置为 INFO 并搜索 "MatmulTiling" 查看 TilingData 各参数值。
- 多核场景的维度:多核 Tiling 中
SetShape描述的是整体计算形状,单核切分形状由SetSingleShape控制(默认 -1 由算法自行推导);切分后的实际单核形状可通过GetSingleShape查询。
通过合理运用SetShape的两种传参方式及其与SetOrgShape的回退配合机制,开发者可以在完整矩阵、局部矩阵、含脏数据矩阵、Ka/Kb 不等长等多样化的 Matmul 场景下,稳定获取正确且性能最优的 Tiling 参数。
- 人工智能
- 深度学习
- 算子库
- CANN
- Ascend
【免费下载链接】asc-devkit
本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。
相关推荐
深入解析 pyasc 中 asc.lib.host.MatmulApiTiling.set_shape:设置 Matmul 矩阵乘计算形状的 Host 侧 Tiling 接口
深入解析 pyasc 中 asc.lib.host.MatmulApiTiling.set_shape:设置 Matmul 矩阵乘计算形状的 Host 侧 Ti
编程语言编译器人工智能CANNAscendasc-devkit Matmul Tiling 之 SetBias 接口详解:控制 Bias 参与矩阵乘运算的开关
asc devkit Matmul Tiling 之 SetBias 接口详解:控制 Bias 参与矩阵乘运算的开关 Matmul 是昇腾 AI 处理器上最核心
人工智能深度学习算子库CANNAscendasc-devkit 中 Matmul Tiling 的 SetSparse 接口详解:Sparse Matmul 稀疏场景设置指南
asc devkit 中 Matmul Tiling 的 SetSparse 接口详解:Sparse Matmul 稀疏场景设置指南 Sparse Matmul
人工智能深度学习算子库CANNAscend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考