CANN graph-autofusion SuperKernel 优化与调试选项实战:AOT 样例 example02_sk_options 全解
2026/9/18 15:28:22 网站建设 项目流程

CANN graph-autofusion SuperKernel 优化与调试选项实战:AOT 样例 example02_sk_options 全解

【免费下载链接】graph-autofusionGraph-autofusion 是一个面向昇腾(Ascend)芯片的轻量级、解耦式组件集合,旨在通过自动融合技术加速模型执行。 目前已开源 SuperKernel 组件和 Autofuse 组件,未来将持续开放更多自动融合相关模块。项目地址: https://gitcode.com/cann/graph-autofusion

本文基于 graph-autofusion 仓库super_kernel/examples/aot/example02_sk_options/下的 AOT 样例,系统讲解 SuperKernel 的 optimize/debug options 如何配置、如何随torch.compile下发到编译管线,以及仓库中SuperKernelOptionsManager对这些选项的解析、校验与默认值处理。读完本文,你能完整跑通该样例(dav-2201/dav-3510双架构),理解super_kernel_optimize_optionssuper_kernel_debug_options中每个开关的语义、取值范围和源码级实现依据,并掌握静态编译产物与 eager 真值校验的工程做法。

一、样例定位与运行方式

该样例(README)的定位是:演示 SuperKernel 的 optimize/debug options,并用 eager 执行结果校验静态编译(static kernel compile)输出。它属于 SuperKernel AOT(Ahead-Of-Time)编译链路的官方示例,与example01_dual_streamexample03_kernel_pybind并列,专注于"编译期选项"这一主题。

在仓库根目录执行:

bash super_kernel/examples/aot/example02_sk_options/run.sh --npu-arch=dav-2201

要点说明:

  • 该样例支持dav-2201dav-3510两种 NPU 架构,通过--npu-arch参数指定,脚本会根据架构选择对应的 attention 网络脚本(run.sh 中的case分支:dav-2201main-dav-2201.pydav-3510main-dav-3510.py);
  • 运行设备为"当前可见 NPU"(脚本本身不做设备选择,由torch_npu默认调度);
  • 前置依赖是torch_npunpugraph_ex编译后端与 SuperKernel 静态编译能力(CANN 环境已安装),运行前请先确认环境。

1.1 run.sh 的完整执行流程

run.sh 只有 26 行核心逻辑,但它串联了完整的"清理—编译—校验—回滚"闭环,值得逐段拆解。其公共函数来自 common.sh(source ../scripts/common.sh):

  1. 参数解析sk_parse_npu_arch基于getopt解析--npu-arch,并做白名单校验(sk_validate_npu_arch只接受dav-2201|dav-3510,其余值报错退出码 2);
  2. 工作区清理sk_cleanup_local删除上一轮残留的logtmpsk_metakernel_metaprofilingstatic_kernel_compile_outputsaclnn_static_shape_kernel_outputs.static_kernel_records.json,保证每次运行从干净状态开始;
  3. 日志捕获执行sk_run_python_with_logtee方式把 Python 进程的全部输出写入tmp/run.log,并通过PIPESTATUS[0]返回真实退出码;
  4. 静态编译产物校验sk_check_static_kernel_outputs ... required检查static_kernel_compile_outputs/下是否生成了*.run安装包,同时排查*_compile_error.log;由于传入了required没有生成.run包即判定样例失败——这正对应该样例"静态编译产物 + eager 真值校验"的双重验收标准;
  5. 退出回滚trap 'sk_uninstall_static_kernel_from_log' EXIT保证无论成功失败退出,都会从run.log中提取本次安装的uninstall.sh路径并执行卸载。该函数还做了严格的安全校验:卸载脚本必须位于$ASCEND_HOME_PATH/opp/static_kernel/ai_core/<包名>/uninstall.sh,与本次生成的*.run包一一对应,拒绝执行符号链接、路径逃逸(含..)或不属于本包目录的脚本,避免误删系统已装的静态内核。

这套"生成即校验、退出即回滚"的脚本结构,对自建 SuperKernel AOT 回归脚本有直接参考价值。

二、被测网络:双架构 attention 图

样例主脚本中的Network是一个刻意构造的多 op 图,用于覆盖 SuperKernel 优化选项的实际作用面。以 main-dav-2201.py 为例,其前向拓扑为:

query, key, value, length | v [fia_01] npu_fused_infer_attention_score | v [res] npu_moe_gating_top_k_softmax_v2 (k=1024) | v [quant] npu_dynamic_quant -> to(float16) | v [ifa_01] npu_incre_flash_attention <--- key, value, length | v [fia_02] npu_fused_infer_attention_score <--- key, value, length | +-----------> torch.add <--- npu_grouped_matmul | v outputs: (add_01, ifa_01)
  • 输入规模:batch=3, seq_len=256, hidden=1024,全部float16上 NPU,length=[99,199,180]表示逐样本变长序列;
  • 图中同时包含 fused attention、MoE gating top-k softmax、动态量化、增量 flash attention、grouped matmul 与 elementwise add,存在跨 op 的数据依赖与并行可能,正是 SuperKernel 跨核融合、op 并行等优化选项需要处理的典型场景。

两个架构版本的主要差异(对比 main-dav-3510.py):

项目dav-2201 版dav-3510 版
中间 attention opnpu_incre_flash_attention(增量解码形态)npu_fused_infer_attention_score(decode 形态)
序列长度参数单一actual_seq_lengths=length拆分为actual_seq_lengths=query_lengthsactual_seq_lengths_kv=kv_lengths(query 长度[1,1,1],模拟 decode 场景)
输出(add_01, ifa_01)(add_01, fia_decode_01)

也就是说,同一套 options 配置会分别作用于两种不同形状的 attention 图上,这对验证选项行为的架构无关性(以及架构相关内部选项的自动开启,见下文)很关键。

三、SuperKernel 优化选项详解

样例通过torch.compile(..., backend="npugraph_ex", options={...})把 SuperKernel 选项带入编译管线,核心字段是super_kernel_optimize: True(总开关)和super_kernel_optimize_options。样例中实际启用的优化选项如下(取自两个主脚本中完全一致的build_model()):

options={ "static_kernel_compile": True, "super_kernel_optimize": True, "super_kernel_optimize_options": { "auto_op_parallel": 0, "dcci_before_kernel_start": [".*"], "dcci_after_kernel_end": [".*"], "dcci_disable_on_kernel": [".*"], "early_start": 1, "aggressive_opt_strategies": { "value_breaker_bypass": 0b10, "task_breaker_bypass": 0b00, }, }, "super_kernel_debug_options": { "debug_sync_all": 0, "debug_op_exec_trace": 0, "debug_cross_core_sync_check": 0, "debug_per_op_max_core_num": 0, }, },

3.1 优化选项逐项解析

各选项的名称、类型、默认值与合法取值范围,由 sk_options_manager.cpp 中的默认选项工厂表(DEFAULT_OPTION_FACTORIES)与SetOptOptionValue解析逻辑共同定义;选项枚举与结构体定义见 super_kernel.h。

选项类型默认值合法范围样例取值与含义
auto_op_parallel整数0[0, 1]0,关闭自动 op 并行
dcci_before_kernel_start字符串列表模式串[".*"],对所有 kernel 在启动前允许 DCCI 调度策略
dcci_after_kernel_end字符串列表模式串[".*"],对所有 kernel 在结束后允许相应 DCCI 策略
dcci_disable_on_kernel字符串列表模式串[".*"],对所有 kernel 施加该禁用策略
early_start整数0(ACLSK_EARLY_START_DISABLED[0, 1]1,启用 early start 全局选项
aggressive_opt_strategies结构体全 0见下激进融合策略开关

补充说明源码中同样注册、但样例未显式设置的优化选项(它们会走默认值):

  • preload_code:整数,默认1,合法范围 [0, 2];
  • split_mode:整数,默认4,合法范围 [1, 4](splitCnt);
  • stream_fusion:整数,默认1,合法范围 [0, 1];
  • kernel_map:kernel 名映射(aclskKernelMapOption,每个条目最多 4 个sknlNames);
  • ubuf_lock_ignore_kernel:字符串列表,配置按名字模式"忽略 MIX kernel split"的 op;
  • opt_extend_option/debug_extend_option:字符串 map 形式的扩展预留位。

3.2 模式串(正则)匹配规则

dcci_*系列选项接受的是 kernel 名模式列表。从源码结构看(SuperKernelOptionsManager::MatchRegexIsValidRegexPattern,sk_options_manager.cpp):

  • 仅支持字符:字母、数字、_-.*(其中.匹配任意字符,*为通配);
  • 模式不允许以*开头,且不能为空;
  • 因此样例中的".*"表示"匹配所有 kernel",是"对全部 op 生效"的写法;实际项目中通常换成如"MatMul_*"这样更窄的模式,只对被怀疑受 DCCI 影响的 kernel 生效。

匹配逻辑基于二维动态规划(matchFlag[m+1][n+1]),对每个 kernel 名逐一尝试列表中所有模式,命中任一即返回真。

3.3 aggressive_opt_strategies:位掩码语义

aggressive_opt_strategies对应 C API 结构体aclskAggressiveOptStrategieseventBreakerBypass/valueBreakerBypass/taskBreakerBypass三个字段),其含义在 super_kernel.h 的注释中定义得很明确:

  • eventBreakerBypass:为 event breaker 策略预留,样例未设置(解析侧校验其取值在 0 到类型上限之间);
  • valueBreakerBypass:值依赖内存等待策略的位掩码,取值为枚举aclskValueBreakerBypassFlag
    • 0b00ACLSK_VALUE_BREAKER_BYPASS_NONE):拒绝 notify/wait 配对关系,保持 wait 不可融合;
    • 0b01ACLSK_VALUE_BREAKER_BYPASS_PAIRED_WAIT):对于"配对"的 notify+wait,仍要求既有规则通过,否则 SuperKernel 优化退出;
    • 0b10ACLSK_VALUE_BREAKER_BYPASS_UNPAIRED_WAIT):对于规则检查后"没有对应 notify 的 wait",放行其融合。样例取0b10,即允许这类单边 wait 参与融合——这是一种更激进(但需自行验证数值正确性)的策略;
  • taskBreakerBypass:为 1 时启用默认节点旁路,合法范围 [0, 1]。样例取0b00即关闭。

解析侧对这三个字段分别调用GetValidatedUintValue做范围校验:越界时打SK_LOGW并回退到默认值(如value_breaker_bypass默认ACLSK_VALUE_BREAKER_BYPASS_NONE),而不是直接报错。

3.4 选项解析与校验机制(源码视角)

SuperKernelOptionsManager::ParseOptions(sk_options_manager.cpp)是选项进入 SuperKernel 的唯一入口,其行为要点:

  1. 先执行RegisterDefaultOptions():注册全部默认选项 → 注册内部选项 → 应用架构相关选项(下一节展开);
  2. 遍历aclskOptions数组逐项调用SetOptOptionValue同一optionType重复出现时只取第一个(后到项打 warning 跳过),因此 Python 侧 options dict 的键不应重复下发;
  3. 数值选项统一走NumberOptOption::SetValue的 [min, max] 区间校验,越界回退默认值;字符串列表选项不允许空列表;
  4. 所有生效值最终可通过ToJson()序列化(sk_dump_json.cpp 相关链路会将其落盘到 JSON dump),便于排查"我下发的选项到底生效成什么样"。

3.5 架构相关的内部选项

ApplyArchSpecificOptions会根据当前 kernel 架构(GetCurrentSkKernelArch(),见 sk_common.h)自动开启内部选项(SkInnerOptionType,用户不可直接设置,只能通过 JSON dump 观察):

  • dav-3510DAV_3510):自动开启mix_kernel_splitsimt_op_support
  • dav-2201DAV_2201):不开启,保持默认。

这解释了样例为何要按架构拆成两套 main 脚本:同样的选项配置,在两种架构上的内部行为基线本身就不同,attention 网络形态(prefill vs decode)也需要分别构造。

四、SuperKernel 调试选项详解

super_kernel_debug_options下的四个开关在样例中全部显式置0(关闭),但它们的语义与联动关系值得讲清楚,默认注册与联动逻辑均在 sk_options_manager.cpp:

调试选项默认值合法范围作用
debug_sync_all0[0, 1]置 1 时进入调试模式(EnableDebug()debug_sync_all == 1),执行路径上加入全同步行为,用于定位跨核时序问题
debug_op_exec_trace0[0, 1]开启 op 级执行 trace
debug_cross_core_sync_check0[0, 1]开启跨核同步检查
debug_per_op_max_core_num0[0, 1]开启"每 op 最大核数"限制调试

一个重要的联动规则:debug_per_op_max_core_num被置 1 时,解析逻辑会自动补开debug_cross_core_sync_check(若其当前不为 1 则自动置 1,并打日志[DEBUG_PER_OP_MAX_CORE_NUM] auto-enabled DEBUG_CROSS_CORE_SYNC_CHECK)。因此在样例中如果只把debug_per_op_max_core_num改为 1,实际生效的调试面会比字面上多一项——读 dump JSON 或日志时可以留意这一自动开启。

调试选项与优化选项的分层设计(super_kernel_optimize_optionsvssuper_kernel_debug_options)让"性能调优实验"与"正确性排查"可以独立开关,这也是该样例将两组选项显式全量列出的原因:它本身就是这两组选项的活文档。

五、正确性校验:eager 真值 vs 静态编译输出

样例main()的验证流程是静态编译可信度的标准姿势(两个主脚本一致):

  1. 固定随机种子(torch.manual_seed(1234)np.random.seed(1234))生成输入;
  2. 先用未编译eager_model跑一遍,torch.npu.synchronize()detach().clone()保存期望输出;
  3. 再用torch.compile(backend="npugraph_ex", fullgraph=True, dynamic=True, options={...})编译后的模型跑同样(clone 后的)输入,得到实际输出;
  4. 对两个输出分别做torch.testing.assert_close(actual, expected, rtol=1e-3, atol=1e-2)
  5. 通过后打印两份输出摘要(shape、dtype、mean)以及真值校验通过 / 测试完成!;失败路径区分返回码:断言失败返回 1(真值校验失败),其他异常返回 2 并打印 traceback。

结合run.shsk_check_static_kernel_outputs ... required,该样例的最终通过条件是"双重的":Python 侧数值校验通过static_kernel_compile_outputs/下确实生成了静态编译*.run包。对dav-2201版还额外校验了npu_incre_flash_attention输出(ifa_out)与add_out两条输出流。

六、延伸阅读:仓库内相关源码与文档

  • 选项定义与 C API:super_kernel.h(aclskOptionType枚举、各aclsk*Option结构体、aclskValueBreakerBypassFlagaclskOptimize接口声明);
  • 选项管理器:sk_options_manager.h(OptOptionBase类型体系、SuperKernelOptionsManager接口与CollectAllOptionsdump 工具)、sk_options_manager.cpp(默认值、范围校验、正则匹配、架构选项、JSON 序列化);
  • 样例脚本:run.sh、main-dav-2201.py、main-dav-3510.py、公共函数 common.sh;
  • 姊妹样例:example01_dual_stream(双流场景)与 example03_kernel_pybind(pybind 自定义 kernel);
  • 背景文档:SuperKernel 开发者指南、SuperKernel 迁移设计,以及仓库内 super_kernel/README.md。

README 中指向的 TorchAir SuperKernel 使用说明属于外部仓库文档,本文不展开;本文所有选项语义均以本仓库super_kernel/源码为准。

七、小结

example02_sk_options用一份双架构 attention 图 + 一组显式列出的 optimize/debug options + eager 真值校验,构成了 SuperKernel 静态编译选项的最小可复现实验闭环。实践建议:

  • 以样例为模板新建回归脚本时,保留"清理 → 编译 → 校验.run产物 → 退出自动卸载"的run.sh结构,可显著降低 AOT 实验的环境污染风险;
  • 调整dcci_*模式串时记住限制字符集(不允许以*开头),".*"只代表全量生效,不应直接搬进生产配置;
  • 尝试value_breaker_bypass=0b10等激进策略后,必须重新走 eager 真值校验流程,并以 options JSON dump 确认实际生效值;
  • dav-3510上注意mix_kernel_split/simt_op_support内部选项的自动开启,行为基线与dav-2201不同。

【免费下载链接】graph-autofusionGraph-autofusion 是一个面向昇腾(Ascend)芯片的轻量级、解耦式组件集合,旨在通过自动融合技术加速模型执行。 目前已开源 SuperKernel 组件和 Autofuse 组件,未来将持续开放更多自动融合相关模块。项目地址: https://gitcode.com/cann/graph-autofusion

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询