在华为 CANN(Compute Architecture for Neural Networks)开发流程中,自定义算子的开发和测试是关键环节。你提到的 mskpp 很可能是拼写误差或特定项目内部的命名,通常在 CANN 生态中,新建算子主要指的是 TBE(Tensor Boost Engine)算子Ascend C 算子
autotune_utils.py 是算子开发中用于自动调优的重要辅助脚本,主要目的是为了寻找让算子在 NPU 上运行性能最佳的参数(如 Tiling 策略、Block 大小等)。

  • autotune_utils.py:通过穷举或启发式搜索,自动帮你测试不同参数组合下的算子运行速度,从而确定最优的 Tiling 策略。
    建议先阅读你所使用的样例代码中 autotune_utils.py 内的具体函数定义,理解它需要传入什么参数(通常是输入数据列表、输出列表、以及参数搜索空间字典),然后照猫画虎编写驱动脚本即可。
    autotune_utils.py 的详细使用指南。

一、 背景介绍:CANN 新建算子与测试

在 CANN 中开发一个新算子,通常包含两个核心阶段:

  1. 算子开发:使用 TIK(Tensor Iterator Kernel,Python DSL)或 Ascend C(C++)编写算子代码,实现计算逻辑。
  2. 算子测试与调优
    • 正确性测试:确保算子在 NPU 上运行的结果与 CPU(如 NumPy)上的 golden data 一致。
    • 性能调优:NPU 的性能极度依赖于数据搬运(GM 到 UB)的策略。如何切分数据、如何利用流水线,需要通过调优来找到最优参数。
      autotune_utils.py 的作用:
      该脚本通常位于算子工程目录下,用于在算子开发完成后,自动遍历不同的 Tiling 参数或配置组合,运行算子并记录耗时,从而帮助开发者找到性能最好的配置。

二、 autotune_utils.py 介绍

autotune_utils.py 并非 CANN 安装包中的全局命令,而是通常包含在 算子工程模板TBE 开发示例 中的一个 Python 工具类。它封装了与 CANN 编译器和运行时交互的底层逻辑。
核心功能:

  • 编译支持:调用 ascendctikc 编译器,生成不同的 .o.so 文件。
  • 运行支持:调用 ACL(Ascend Computing Language)接口加载算子并在设备上执行。
  • 性能采样:利用 NPU 的 Profiling 接口或简单的 Python time 库,统计算子运行耗时。
  • 参数搜索:提供简单的网格搜索或随机搜索框架,用于遍历 Tiling 参数。

三、 如何使用 autotune_utils.py 进行测试

以下是一个典型的使用流程。假设你已经写好了基于 TIK 或 Ascend C 的算子代码。

1. 环境准备

确保你已经设置了 CANN 的环境变量:

source /usr/local/Ascend/ascend-toolkit/set_env.sh
2. 准备算子工程目录

你的目录结构通常如下:

my_custom_op/
├── src/
│   └── add_custom.cpp        (或 .py) # 你的算子实现代码
├── inc/
│   └── add_custom.h
├── tests/
│   ├── test_add_custom.py    # 单元测试脚本
│   └── autotune_utils.py     # 自动调优工具
└── build.sh                  # 编译脚本
3. 编写调用脚本

通常你不需要直接修改 autotune_utils.py,而是编写一个 Python 脚本(如 run_tune.py)来调用它。
假设 autotune_utils.py 中提供了一个类似 auto_tune 的函数(具体函数名需查看你手中的文件内容,常见的有 run_tunetune_op)。
示例代码逻辑:

import numpy as np
from autotune_utils import tune_op  # 假设这是工具类提供的入口函数
# 1. 定义输入输出数据
shape = (1024, 1024)
input_x = np.random.uniform(-10, 10, shape).astype(np.float16)
input_y = np.random.uniform(-10, 10, shape).astype(np.float16)
output_z = np.zeros(shape).astype(np.float16)
# 2. 定义调优参数空间
# 这是非常关键的一步。你需要告诉工具哪些参数是可以变化的。
# 例如:UB切分块的大小,是否开启双缓冲等。
tune_range = {
    "block_dim": [8, 16, 32],           # 不同的 Block 维度
    "ub_factor": [1, 2, 4],             # 不同的 UB 利用倍率
    "enable_double_buffer": [True, False]
}
# 3. 调用 Autotune 工具
# 这将自动编译不同版本的算子,运行并记录时间
best_config, best_time = tune_op(
    op_name="add_custom",
    op_func=None,          # 某些工具需要直接传入算子函数,有些只需传算子名
    inputs=[input_x, input_y],
    outputs=[output_z],
    tune_params=tune_range,
    repeat_num=100,        # 每次运行 100 次取平均
    compiler_path="build/src/add_custom.so" # 已编译的算子库路径
)
print(f"Best Config: {best_config}")
print(f"Best Time: {best_time} us")
4. 执行与结果分析

运行你的 Python 脚本:

python3 run_tune.py

预期输出:
脚本会在终端打印调优过程,类似于:

Running config: {'block_dim': 8, 'ub_factor': 1} ... Time: 150.5 us
Running config: {'block_dim': 8, 'ub_factor': 2} ... Time: 120.1 us
...
Running config: {'block_dim': 32, 'ub_factor': 4} ... Time: 85.2 us
[INFO] Autotune finished.
[INFO] Best performance: 85.2 us with params: {'block_dim': 32, 'ub_factor': 4}
5. 固化参数

找到最佳参数后,你需要将这些参数回填到你的算子代码中(例如在 GetTilingKeyTilingContext 中硬编码,或者编写相应的 Tiling 算法逻辑),以确保算子在正式部署时始终使用最高效的策略。

四、 常见注意事项

  1. 算子编译:在使用 autotune_utils 前,确保你的算子已经被正确编译成 .so.o 文件,并且没有语法错误。Autotune 主要是为了找性能参数,而不是为了找语法 Bug。
  2. 数据精度:测试时尽量使用较小的数据 Shape(如 (16, 16)(128, 128))来快速验证逻辑,使用大 Shape(如 (4096, 4096))来进行性能调优。
  3. 设备可用性:确保当前机器上有 NPU 设备(Ascend 310/310P/910 等),且驱动状态正常,可以使用 npu-smi info 查看。
  4. 版本差异:不同版本的 CANN(如 5.0.2, 6.0, 7.0)中,autotune_utils.py 的实现可能不同。请务必参考你当前 CANN 版本对应样例中的代码注释。

总结

你提到的场景是典型的华为昇腾算子开发性能调优环节。

  • 新建算子:指实现前向计算逻辑。
  • 测试:验证结果正确性。
  • autotune_utils.py:通过穷举或启发式搜索,自动帮你测试不同参数组合下的算子运行速度,从而确定最优的 Tiling 策略。
    建议先阅读你所使用的样例代码中 autotune_utils.py 内的具体函数定义,理解它需要传入什么参数(通常是输入数据列表、输出列表、以及参数搜索空间字典),然后照猫画虎编写驱动脚本即可。
Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐