深入解析 CANN pyascMatmulApiTiling.set_split_range:baseM/baseN/baseK 切分范围约束与 C0_size 对齐机制
【免费下载链接】pyasc本项目为Python用户提供算子编程接口,支持在昇腾AI处理器上加速计算,接口与Ascend C一一对应并遵守Python原生语法。项目地址: https://gitcode.com/cann/pyasc
本指南围绕 CANN pyasc 开源仓库中asc.lib.host.MatmulApiTiling.set_split_range这一 Host 侧 Matmul Tiling API 展开,讲解其函数签名、六个切分范围参数的语义与默认值、返回值约定,以及计算 Tiling 时的 C0_size 对齐约束。读完本文,你将理解 baseM/baseN/baseK 在 Matmul Tiling 中的角色,掌握该接口与set_fix_split、MultiCoreMatmulTiling.set_single_range等切分控制接口的差异,并能在实际算子开发中正确使用该接口(或明确判断其适用性)。
接口定位:Host 侧 Matmul Tiling 参数计算链路中的一环
set_split_range是asc.lib.host模块中 MatmulApiTiling 系列接口之一。该系列接口用于在 Host 侧获取 Matmul kernel 计算所需的 Tiling 参数:用户只需要传入 A/B/C 矩阵的 Position 位置、Format 格式和 DType 数据类型等信息,调用 API 接口,即可获取 Init 中TCubeTiling结构体中的相关参数。
在 pyasc 中,MatmulApiTiling、MultiCoreMatmulTiling、BatchMatmulTiling三个类共享一组"共有接口",set_split_range即其中之一(见 host.md 中的接口列表)。它对应 Ascend C 原生的SetSplitRange接口,用于设置 Tiling 计算过程中 baseM/baseN/baseK 的最大值和最小值,从而把 Tiling 函数自动计算出的 base 尺寸约束在指定区间内。
在 pyasc 的 Python 侧,接口先由类型桩声明,再通过 pybind11 绑定到 C++ 实现:
- 类型桩声明位于 wrappers.py,签名与文档一致,六个参数均有默认值;
- C++ 绑定位于 bindings/MatmulApiTiling.cpp,通过
py::class_<MatmulApiTiling, MatmulApiTilingBase>上的.def("set_split_range", ...)注册,实际调用MatmulApiTilingBase::SetSplitRange。
从绑定代码可以看到,六个参数的默认值("max_base_m"_a = -1等)在 pybind11 层以关键字参数默认值的形式提供,与 Python 侧类型桩保持一致,这也意味着调用时可以只传需要约束的维度,其余维度保持"不设置"。
函数签名与参数语义
函数原型
MatmulApiTiling.set_split_range( self: libhost.MatmulApiTilingBase, max_base_m: SupportsInt = -1, max_base_n: SupportsInt = -1, max_base_k: SupportsInt = -1, min_base_m: SupportsInt = -1, min_base_n: SupportsInt = -1, min_base_k: SupportsInt = -1, ) -> int对应的 Ascend C 函数原型为:
int32_t SetSplitRange(int32_t maxBaseM = -1, int32_t maxBaseN = -1, int32_t maxBaseK = -1, int32_t minBaseM = -1, int32_t minBaseN = -1, int32_t minBaseK = -1)参数类型为SupportsInt,即任何支持整数转换的 Python 对象均可传入;在 C++ 绑定层统一转换为int32_t后传给SetSplitRange。
六个参数的含义
| 参数 | 含义 | 默认值 | 默认值语义 |
|---|---|---|---|
max_base_m | 设置最大的 baseM 值 | -1 | 不设置 baseM 最大值,由 Tiling 函数自行计算 |
max_base_n | 设置最大的 baseN 值 | -1 | 不设置 baseN 最大值,由 Tiling 函数自行计算 |
max_base_k | 设置最大的 baseK 值 | -1 | 不设置 baseK 最大值,由 Tiling 函数自行计算 |
min_base_m | 设置最小的 baseM 值 | -1 | 不设置 baseM 最小值,由 Tiling 函数自行计算 |
min_base_n | 设置最小的 baseN 值 | -1 | 不设置 baseN 最小值,由 Tiling 函数自行计算 |
min_base_k | 设置最小的 baseK 值 | -1 | 不设置 baseK 最小值,由 Tiling 函数自行计算 |
其中,baseM/baseN/baseK 是 Matmul Tiling 的核心概念:baseM、baseN 表示每个计算分块(Tile)在 M、N 方向上的尺寸,baseK 表示 K 方向上一次累加的分块尺寸。base 尺寸直接决定 L0/L1 Buffer 的占用和循环次数,是 Tiling 函数内部自动计算的核心输出之一,可通过 get_base_m、get_base_n、get_base_k 三个接口在get_tiling完成后读取。
返回值说明
-1:设置失败;0:设置成功。
重要约束:当前版本 Tiling 暂不支持该功能
文档与绑定代码中的描述均明确标注:"目前 Tiling 暂时不支持该功能"。也就是说,在 pyasc 当前仓库对应的 Tiling 实现中,调用该接口会被接受(绑定层会正常调用SetSplitRange),但 Tiling 计算并不会真正使用这一范围约束。这一点务必在阅读和选型时注意,避免误以为设置了set_split_range就能约束 base 尺寸。如果你的目标是固定 base 尺寸,应改用 set_fix_split(固定 baseM/baseN/baseK 的具体值);如果是多核场景约束单核切分尺寸,应使用 MultiCoreMatmulTiling.set_single_range。
C0_size 对齐约束:设置值不满足对齐时由 Tiling 自动对齐
set_split_range的约束说明揭示了 Tiling 内部对 base 尺寸的对齐规则:
若 base_m/base_n/base_k 不满足 C0_size 对齐,计算 Tiling 时会将该值对齐到 C0_size。
C0_size 是昇腾 Cube 单元计算的基本对齐粒度,其取值与数据类型相关:
| 数据类型 | C0_size |
|---|---|
| half / bfloat16_t | 16 |
| float | 8 |
| int8_t | 32 |
| int4b_t | 64 |
这一对齐规则与同族接口 set_fix_split 的约束相互印证:后者明确要求 base_m 需要小于等于 single_m 按 16 个元素向上对齐后的值(如ceil(single_m/16)*16),base_n 需要小于等于 single_n 以 C0_size 个元素向上对齐的值,且 base 尺寸还需满足分形对齐要求,否则获取 Tiling 将失败。可以推断,set_split_range中设置的最小值/最大值在实际参与 Tiling 计算时,同样会先被对齐到 C0_size 的整数倍,因此传入非对齐的值不会直接报错,但最终生效的 base 尺寸可能是对齐后的值。
从实现结构上看,这一约束语义体现在 bindings/MatmulApiTiling.cpp 的接口文档中,对齐逻辑则位于底层的 Tiling 库实现(pyasc 通过 loader.py 加载的 Host 侧动态库),这也是为什么文档建议以 C0_size 对齐的整数倍传入,以避免因对齐导致的尺寸"意外放大"。
调用示例与典型使用模式
基本调用模式
set_split_range通常与其他设置接口配合使用,完整调用序列如下(参数仅为演示):
import asc.lib.host as host ascendc_platform = host.get_ascendc_platform() tiling = host.MatmulApiTiling(ascendc_platform) # 设置 A/B/C/Bias 的 Position、Format、DataType tiling.set_a_type(host.TPosition.GM, host.CubeFormat.ND, host.DataType.DT_FLOAT16) tiling.set_b_type(host.TPosition.GM, host.CubeFormat.ND, host.DataType.DT_FLOAT16) tiling.set_c_type(host.TPosition.GM, host.CubeFormat.ND, host.DataType.DT_FLOAT) tiling.set_bias_type(host.TPosition.GM, host.CubeFormat.ND, host.DataType.DT_FLOAT) # 设置形状与 buffer 空间 tiling.set_shape(1024, 1024, 1024) tiling.set_org_shape(1024, 1024, 1024) tiling.set_bias(True) # 设置 baseM/baseN/baseK 的最大值与最小值 ret = tiling.set_split_range(max_base_m=256, max_base_n=256, max_base_k=-1, min_base_m=16, min_base_n=16, min_base_k=-1) assert ret == 0, "set_split_range failed" tiling.set_buffer_space(-1, -1, -1) # 计算 Tiling 并读取结果 tiling_data = host.TCubeTiling() ret = tiling.get_tiling(tiling_data) base_m = tiling.get_base_m() base_n = tiling.get_base_n() base_k = tiling.get_base_k()需要特别说明:由于当前 Tiling 版本暂不支持该功能,上面的set_split_range调用不会真正影响get_tiling的结果。若确实需要约束 base 尺寸,请参考下一节的替代方案。
与相近接口的对比与选型
| 接口 | 作用 | 适用场景 | 当前可用性 |
|---|---|---|---|
set_split_range | 设置 baseM/baseN/baseK 的最大值与最小值 | 希望把自动计算的 base 尺寸约束在区间内 | 当前 Tiling 暂不支持 |
| set_fix_split | 固定 baseM/baseN/baseK 的具体值 | 固定切分尺寸,如set_fix_split(16, 16, -1) | 可用 |
| MultiCoreMatmulTiling.set_single_range | 设置 single_core_m/n/k 的最大值与最小值 | 多核切分时约束单核计算尺寸 | 可用 |
| MultiCoreMatmulTiling.set_align_split | 设置单核切分尺寸的对齐值 | 多核切分时控制对齐粒度 | 可用 |
其中set_fix_split与set_split_range的语义最接近(都作用于 base 尺寸),但前者是"固定值"、后者是"区间约束";set_single_range则作用于多核场景的单核尺寸,与 base 尺寸是不同的粒度层级。选型建议:
- 单核 Tiling 需要固定 base 尺寸 →
set_fix_split; - 多核 Tiling 需要约束单核尺寸 →
MultiCoreMatmulTiling.set_single_range; - 需要 base 尺寸区间约束 → 关注
set_split_range,但需确认所用 Tiling 版本已支持该能力。
源码实现佐证:从 Python 类型桩到 C++ 绑定的完整链路
set_split_range的完整调用链路在 pyasc 仓库中可逐层追溯:
- Python 类型桩:wrappers.py 中
MatmulApiTilingBase.set_split_range声明六个int参数并返回int,供静态类型检查与 IDE 提示使用; - pybind11 绑定:bindings/MatmulApiTiling.cpp 中通过
py::class_<MatmulApiTiling, MatmulApiTilingBase>注册该方法,lambda 将六个 Python 参数转为int32_t后调用self.SetSplitRange(...),关键字默认值-1在此层声明; - C++ 原生接口:
MatmulApiTilingBase::SetSplitRange即 Ascend C 的SetSplitRange,对应文档中给出的 C++ 原型; - 枚举与平台对象:示例中的
TPosition、CubeFormat、DataType、MatrixTraverse等均在 wrappers.py 中以ProxyBase子类形式暴露(如CubeFormat的ND/NZ/NN等成员),运行时通过Loader.get_attr代理到 C++ 对象。
由于 wrappers.py 中的ProxyMeta元类会在__call__和__getattribute__中把 Python 侧的类访问转发到由Loader加载的 C++ 类,因此类型桩中的...仅是静态占位,真正的行为由 bindings/MatmulApiTiling.cpp 中 pybind11 定义的 C++ 实现决定——set_split_range也不例外。
总结
set_split_range用于设置 baseM/baseN/baseK 的最大值与最小值,六个参数均有-1默认值,-1表示"不设置、由 Tiling 函数自行计算";- 返回值
0表示设置成功,-1表示设置失败; - 传入的 base 尺寸若不满足 C0_size 对齐,Tiling 计算时会自动对齐到 C0_size(half/bfloat16_t 为 16,float 为 8,int8_t 为 32,int4b_t 为 64);
- 当前 Tiling 版本暂不支持该功能,实际约束 base 尺寸请优先使用
set_fix_split(单核固定 base)或MultiCoreMatmulTiling.set_single_range(多核单核尺寸范围); - 接口完整链路为:Python 类型桩(wrappers.py)→ pybind11 绑定(bindings/MatmulApiTiling.cpp)→ Ascend C
SetSplitRange原生实现,可通过上述路径在仓库中继续深入。
【免费下载链接】pyasc本项目为Python用户提供算子编程接口,支持在昇腾AI处理器上加速计算,接口与Ascend C一一对应并遵守Python原生语法。项目地址: https://gitcode.com/cann/pyasc
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考