- 人工智能
- 深度学习
- 算子库
- CANN
- Ascend
【免费下载链接】asc-devkit
本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。
导读
SetOrgShape是 asc-devkit 中 Matmul Tiling 高阶 API 家族的关键成员,用于在 Matmul 计算前设置矩阵的原始完整形状M、N、K(或 Ka/Kb),单位为元素个数。它解决的是"实际参与 Matmul 计算的形状"与"GM 中数据真实存放的原始形状"不一致时的地址偏移计算问题。读完本文,你将掌握SetOrgShape两种重载的原型与参数语义、与SetShape的配合规则、Ka≠Kb 场景的适用条件,并能结合仓库源码理解该接口从 Host 侧 Tiling 到 Kernel 侧 KFC 消息传递再到设备侧形状校验的完整调用链。
功能说明
SetOrgShape用于设置 Matmul 计算时的原始完整的形状M、N、K 或 Ka/Kb,所有参数的单位均为元素个数。
所谓"原始完整的形状",指矩阵在 Global Memory(GM)中真实存放的完整尺寸;而SetShape设置的是本次实际参与 Matmul 计算的 m/n/k。在多数常规场景下两者相同,但在局部输出(Partial Output)、数据对齐、维度裁剪(ND 对齐、format 转换)等场景中,实际计算的子块尺寸会小于原始完整尺寸。此时 Matmul 高阶 API 在搬运 A/B 矩阵时,必须依据原始完整形状计算各核、各迭代块的源地址偏移,否则将搬错数据。这正是SetOrgShape的核心价值。
函数原型
SetOrgShape提供两个重载,分别对应"Ka 与 Kb 相等"和"Ka 与 Kb 不相等"两种场景:
int32_t SetOrgShape(int32_t orgMIn, int32_t orgNIn, int32_t orgKIn)int32_t SetOrgShape(int32_t orgMIn, int32_t orgNIn, int32_t orgKaIn, int32_t orgKbIn)两个重载的声明位于 include/adv_api/matmul/matmul_tiling_base.h,属于MatmulApiTilingBase基类接口,被MatmulApiTiling、MultiCoreMatmulTiling等派生类共同继承使用。
参数说明
表1参数说明
| 参数名 | 输入/输出 | 描述 |
|---|---|---|
| orgMIn | 输入 | 设置原始完整的形状 M 大小,单位为元素。 |
| orgNIn | 输入 | 设置原始完整的形状 N 大小,单位为元素。 |
| orgKIn | 输入 | 设置原始完整的形状 K 大小,单位为元素。原始完整形状 Ka=Kb 时可设置。 |
| orgKaIn | 输入 | 设置矩阵 A 原始完整的形状 Ka 大小,单位为元素。 |
| orgKbIn | 输入 | 设置矩阵 B 原始完整的形状 Kb 大小,单位为元素。 |
补充说明(结合源码):
- 从 impl/adv_api/tiling/matmul/matmul_tiling_base.cpp 的实现可以看到,三参数重载并不是独立的存储逻辑,而是直接委托给四参数重载:
int32_t MatmulApiTilingBase::SetOrgShape(int32_t orgMIn, int32_t orgNIn, int32_t orgKIn) { return SetOrgShape(orgMIn, orgNIn, orgKIn, orgKIn); }即三参数版本等价于SetOrgShape(orgM, orgN, orgK, orgK),自动将 Ka 和 Kb 都设置为 orgKIn,因此只有当原始完整形状满足 Ka=Kb 时才可使用。
- 四参数重载将输入分别写入成员
orgM、orgN、orgKa、orgKb,并输出调试日志:
int32_t MatmulApiTilingBase::SetOrgShape(int32_t orgMIn, int32_t orgNIn, int32_t orgKaIn, int32_t orgKbIn) { TILING_LOG_DEBUG("Set Original M: %d", orgMIn); TILING_LOG_DEBUG("Set Original N: %d", orgNIn); TILING_LOG_DEBUG("Set Original Ka: %d", orgKaIn); TILING_LOG_DEBUG("Set Original Kb: %d", orgKbIn); this->orgM = orgMIn; this->orgN = orgNIn; this->orgKa = orgKaIn; this->orgKb = orgKbIn; return 0; }- Tiling 对象构造时,
orgM、orgN、orgKa、orgKb均被初始化为 -1(见 matmul_tiling_base.cpp),-1 用作"未显式设置"的哨兵值,这一细节决定了SetShape与SetOrgShape的先后关系(见下文)。
返回值说明
0:设置成功。-1:设置失败。
需要说明的是,从当前仓库实现看,四参数重载对合法输入直接赋值并返回 0,接口本身未设置显式失败分支;数值合法性的强校验发生在设备侧(见下文"约束说明"),因此实际使用时除检查返回值外,更应保证传入的原始形状为正整数。
约束说明
参数 orgKaIn 和 orgKbIn 可以不相等,即原始矩阵形状 Ka 和 Kb 可以不相等。这里的 Ka/Kb 并不是实际 Matmul 计算时的 K(数学上 C=A×B 要求 A 的列数等于 B 的行数,实际参与计算时 Ka 必须等于 Kb),此参数只用于辅助 Matmul API 搬运时的偏移计算。
原始形状必须为正数:设备侧
MatmulShapeInfo的CheckOrgShape会对 orgM、orgN、orgKa、orgKb 逐一断言大于 0,否则报错并终止(见 impl/adv_api/detail/matmul/param/matmul_shape_info.h):
ASCENDC_ASSERT((orgM > 0), { KERNEL_LOG(KERNEL_ERROR, "orgM is %d , which should be larger than 0", orgM); }); ASCENDC_ASSERT((orgN > 0), { KERNEL_LOG(KERNEL_ERROR, "orgN is %d , which should be larger than 0", orgN); }); ASCENDC_ASSERT((orgKa > 0), { KERNEL_LOG(KERNEL_ERROR, "orgKa is %d , which should be larger than 0", orgKa); }); ASCENDC_ASSERT((orgKb > 0), { KERNEL_LOG(KERNEL_ERROR, "orgKb is %d , which should be larger than 0", orgKb); });调用示例
以下示例来自原文档,演示了在 Host 侧 Tiling 计算流程中先调用SetShape再调用SetOrgShape的典型用法:
auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); matmul_tiling::MatmulApiTiling tiling(ascendcPlatform); tiling.SetShape(1024, 1024, 1024); tiling.SetOrgShape(1024, 1024, 1024); // 设置原始完整的形状与 SetShape 的配合规则
结合 matmul_tiling_base.cpp 中SetShape的实现,可以得出两条重要的调用规则:
int32_t MatmulApiTilingBase::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; this->orgN = n; this->orgKa = k; this->orgKb = k; } return 0; }- 规则一(回填逻辑):如果在调用
SetOrgShape之前先调用了SetShape,且四个 org 成员仍为初始值 -1,则SetShape会自动把 m/n/k 回填为原始形状(orgM=m、orgN=n、orgKa=k、orgKb=k)。这意味着"先 SetShape、后 SetOrgShape"时,SetOrgShape的显式值会覆盖回填值;而完全省略SetOrgShape时,原始形状默认等于SetShape的输入。 - 规则二(先后顺序):反过来,若先调用
SetOrgShape再调用SetShape,回填条件已不成立,SetShape只更新实际计算形状 singleM/singleN/singleK,原始形状保持SetOrgShape设置的值,两者互不影响。
在 matmul_advanced_api 示例 中可以看到两者的标准配合注释:
// SetOrgShape设置原始完整矩阵形状,SetShape设置本次实际参与Matmul计算的m/n/k。 // 本样例计算完整矩阵乘,没有局部矩阵或脏数据列,因此两者都设置为M/N/K。 tilingApi.SetOrgShape(M, N, K); tilingApi.SetShape(M, N, K);源码级原理:从 Host Tiling 到 Kernel 计算侧
SetOrgShape设置的信息最终要作用于设备侧 A/B 矩阵搬运的偏移计算,其跨侧传递链路如下。
1. Host 侧:Tiling 对象持有原始形状
MatmulApiTilingBase通过orgM/orgN/orgKa/orgKb四个成员保存原始形状,供后续GetTiling生成TCubeTiling时使用,tiling 结果中的 M、N、Ka、Kb 字段即为搬运偏移计算的依据。
2. Kernel 侧:Matmul 对象通过 KFC 消息下发给 Cube
Kernel 侧的Matmul模板类同样提供SetOrgShape,见 include/adv_api/matmul/matmul_client.h。其三参数版本会委托给五参数版本:
__aicore__ inline void SetOrgShape(int orgM, int orgN, int orgK) { ... SetOrgShape(orgM, orgN, orgK, orgK, orgN); }五参数版本则将 orgM/orgN/orgKa/orgKb/orgKc 写入 KFC(Kernel Function Call)消息体kfcMsg_,并通过PostMessage<KFC_Enum::MMFUN_SET_ORG_SHAPE, false>()发送给 Cube 侧执行,实现 AIC 核与 Cube 核之间的形状信息同步。消息发送的字段数量还受配置开关控制(见 matmul_client.h):
} else if constexpr (ToMatmulConfig(MM_CFG).enableSetOrgShape) { SendSSbufData<7>(msgSrc, msgDst); }3. 设备侧:MatmulShapeInfo 存储并校验
设备侧MatmulShapeInfo类在 impl/adv_api/detail/matmul/param/matmul_shape_info.h 中提供SetOrgM/SetOrgN/SetOrgKa/SetOrgKb/SetOrgKc及整体SetOrgShape(orgM, orgN, orgKa, orgKb, orgKc),对应内部成员M_/N_/Ka_/Kb_/Kc_。在InitParams中,设备侧会直接以 tiling 结果回填原始形状:
const auto& tiling = MATMUL_MODULE(MatmulShapeTiling)->GetTiling(); SetOrgShape(tiling.GetM(), tiling.GetN(), tiling.GetKa(), tiling.GetKb(), tiling.GetN());4. 配置开关:enableSetOrgShape
include/adv_api/matmul/matmul_config.h 中定义了接口的启用开关:
bool enableSetOrgShape = true; // true: The SetOrgShape function needs to be called during Matmul computation默认值为 true,即 Matmul 计算过程中需要调用SetOrgShape完成原始形状的传递;若将其配置为 false,则 KFC 消息发送走更紧凑的分支,原始形状相关字段不参与传输。
典型使用场景
场景一:完整矩阵乘(Ka=Kb)
计算完整的 C=A×B,原始形状与实际计算形状一致,直接使用三参数重载即可,这是最常见也是文档调用示例展示的用法:
tiling.SetShape(1024, 1024, 1024); tiling.SetOrgShape(1024, 1024, 1024);Kernel 侧对应写法(摘自 matmul_advanced_api.asc):
// SetOrgShape设置原始完整矩阵形状,单位为元素。接口要求在SetTensorA、SetTensorB之前调用。 mm.SetOrgShape(tiling.M, tiling.N, tiling.Ka, tiling.Kb);注意示例注释中强调的调用时机:SetOrgShape必须在SetTensorA、SetTensorB之前调用,以确保搬运偏移在设置 A/B 地址前已就绪。
场景二:局部输出 / 形状裁剪(orgShape 与 shape 不一致)
当实际参与计算的形状小于原始完整形状时(例如 Matmul Partial Output、ND 格式对齐、脏数据列裁剪等),必须显式设置原始完整形状,否则各核的搬运偏移会按裁剪后的形状计算而错位。见 matmul_partial_output 示例:
matmulObj.SetOrgShape(tiling.M, tiling.N, tiling.Ka, tiling.Kb);场景三:Ka 与 Kb 不相等
当 A 矩阵原始 K 维与 B 矩阵原始 K 维不相等时,使用四参数重载分别指定。仓库测试 test_matmul_api_tiling.cpp 中有对应的非对称用例,例如:
tiling.SetOrgShape(1024, 1024, 1024, 1280); // orgKa=1024, orgKb=1280需要强调的是,这并不违反矩阵乘法规则:实际参与 Matmul 计算的 K(SetShape中的 k)仍然要求 Ka=Kb 的数学约束;这里的原始 Ka/Kb 只服务于搬运偏移计算,允许不等。
场景四:仅设置原始形状,计算形状自动推导
仓库测试中还存在"只设 orgShape、shape 传 -1"的用法(见 test_matmul_api_tiling.cpp):
tilingApi.SetOrgShape(65536, 64, 64); tilingApi.SetShape(-1, -1, -1); // 实际计算形状由 tiling 依据原始形状与硬件约束推导此时SetShape(-1, -1, -1)表示实际参与计算的 m/n/k 交由 tiling 流程自动推导,原始形状以SetOrgShape为准。
测试验证
SetOrgShape的覆盖面在仓库测试中非常广,可作为回归验证与参考:
- tests/api/adv_api/tiling/test_matmul_api_tiling.cpp:涵盖多核 NZ 输入输出(
SetOrgShape(736, 7168, 4096)配合SetShape(736, 7168, 4096))、B 侧 TSCM 格式、转置场景下的非对齐形状(SetOrgShape(4095, 5121, 4095))、小形状对齐、极端形状(65536×32768×65536)以及 Ka≠Kb 的SetOrgShape(1024, 1024, 1024, 1280)等数十种组合。 - tests/api/adv_api/tiling/test_tiling.cpp:在 RNN、STFT、稀疏 Matmul、量化等大量业务场景中调用
SetOrgShape,验证其在真实算子形态下的正确性。 - tests/api/adv_api/matmul/test_matmul_shape_info.cpp:设备侧
MatmulShapeInfo的SetOrgShape(singleM, singleN, singleK, singleK, singleN)形态调用,验证形状信息在设备侧的落位。
总结
SetOrgShape是 asc-devkit Matmul Tiling 体系中"原始形状"信息的唯一入口,它与SetShape构成"原始完整形状 + 实际计算形状"的双通道描述,二者通过 -1 哨兵值建立了清晰的默认回填规则。理解SetOrgShape的三参数/四参数重载差异、Ka≠Kb 的适用边界以及 Host→KFC→设备侧的传递链路,是在编写局部输出、非对齐、非对称 K 维等高阶 Matmul 算子时正确设置搬运偏移的前提。
- 人工智能
- 深度学习
- 算子库
- 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 中 ascendc_assert 断言接口的调试实践:基于矩阵乘法样例的用法解析与底层原理
asc devkit 中 ascendc_assert 断言接口的调试实践:基于矩阵乘法样例的用法解析与底层原理 导读 ascendc_assert 是 asc
人工智能深度学习算子库CANNAscendJSqlParser源码解析:Expression接口设计与实现原理
JSqlParser源码解析:Expression接口设计与实现原理 引言:SQL解析的核心挑战 在现代数据处理系统中,SQL语句的解析与处理是核心功能之一。无
数据库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考