已合并
feat: add SoC-specific ATT performance model #2490
zhang_shengjie创建于 17 天前
feat: add SoC-specific ATT performance model #2490
已合并
Pull Request已成功合入, 合并人@CANN-robot
(感谢 zhang_shengjie 的贡献)17 天前 创建了 pull request,commit 0ef8b905
atomgit-bot
17 天前 评论:
17 天前 评论:
🤖 正在生成合并请求摘要,请稍候…


不准确?
atomgit-bot
17 天前 评论:
17 天前 评论:
🤖 AI 代码检视正在进行中,请稍候…


不准确?
17 天前 添加了label:cann-cla/yes
CANN-robot
17 天前 评论:
17 天前 评论:
Thanks for your pull-request.
The full list of commands accepted by me can be found at here.
You can get sig-info at here.
You can self-configure the PR merge rules for this repository. For more details, please refer to Here.
For more, you also can visit HICANN.
PR Approval Progress
✅ Congratulations! All modules have met the lgtm and approve requirements.
Module Approval Details
| module | lgtm status | approve status |
|---|---|---|
| repo-cann/graph-autofusion | ✅ yangyongqiang0606, xchu42, wangxiaotian995, liyuewei (4/2) | ✅ yangyongqiang0606 (1/1) |
💡 Tip:
- Committer can comment
/approveor/lgtm- Commenting
/approveimplies both code review (lgtm) and intent to merge (approve)
CLA Signature Pass
zhang_shengjie, thanks for your pull request. All authors of the commits have signed the CLA. 👍


此处折叠了98条消息 查看更多
13 天前 添加了label:lgtm
liyuewei
13 天前 评论:
13 天前 评论:
/lgtm


yangyongqiang
12 天前 评论:
12 天前 评论:
/approve


12 天前 添加了label:approved
12 天前 合入了pull request
描述
一、主要解决的问题
1.1 V35 需要同时携带 NpuArch 与完整 SoC
原有
PlatformInfo.soc_ver承担 NpuArch 语义,V35 无法区分同一架构下的具体 SoC。本次保留旧字段和旧接口布局,新增内部完整 SoC 状态与SetPlatformTarget/GetPlatformTarget,Pythonset_platform增加可选第四个位置参数。1.2 历史性能模型需要按完整 SoC 做少量差异合成
新增 SoC 性能配置核心,按
(NpuArch, full_soc_version)精确绑定目标,复用历史 JSON 基线并合成显式差异;校验成功后才发布只读缓存,避免目标间参数串用。1.3 ASCIR / AscendC 需要稀疏函数替换
包装层读取同一目标副本,先按原工厂注册名创建对象,再按注册名解析 ASCIR / AscendC 覆盖。空覆盖保留原函数;显式覆盖的源项或目的函数不存在时失败,不回退到默认函数,也不叠加成本。
1.4 公开入口需要提前失败并正确传播异常
ATT 建模、公开 codegen 和 Python backend 在进入 PGO / 图处理前校验目标;公式失败不提交节点成本;Python codegen 的
runtime_error转为 Python 异常,不再返回部分 host 结果。1.5 既有 V35 测试夹具需要显式完整 SoC
为进入新路径的旧夹具统一安装 V35 测试平台,保留原基线成本语义,避免只设置
3510后因缺少完整 SoC 而误报。1.6 配置缓存需要避免临时对象地址复用并降低重复解析成本
临时配置不持久缓存,避免地址复用误命中;内置表缓存校验和合成结果,后续函数解析只查当前 API。机制和验证见软件设计 3。
二、修改方案
requires_full_soc_version,仅 V35 取完整 SoC,一次设置平台。soc_perf_config负责目标校验、JSON 合成、只读缓存和两类覆盖解析。InstallV35SocPerfRuntimeStub。各项数据结构、接口和边界见下文软件设计 1–3。
三、代码修改流程图
graph TD A[Python 或 C++ 入口] -->|target| B[读取双维度目标] B -->|query| C{是否需要完整 SoC} C -->|No| D[原 V2 路径] C -->|Yes| E[校验目标与配置] E -->|Invalid| X[生成前失败] E -->|Valid| F[合成历史 JSON 参数] F -->|resolve| G[解析 API 覆盖] G -->|generate| H[建模与代码生成] H -->|Error| Y[传播错误] H -->|Success| Z[返回完整结果]四、lite 设计:需求 1–3 与软件设计关联
4.1 设计目的、范围及约束
复用历史 JSON 和原工厂/函数注册表,不新增 profile 身份、版本或 variant 注册层。
范围为 JSON 系数、API 函数覆盖和错误接收;VF、头成本、NDDMA / RegBase 沿用基线。真实模型、大量标定、新 schema 和调度差异另评估。不改图/pass 或 SuperKernel 接口,参数变化可能影响 tiling。
完整请求串行执行,期间目标固定。原子设置不等于整链并发安全;旧公式再次进入包装仍重新读取目标,不承诺整批只读一次或跨目标并发建模。
SetPlatformTarget、ReadSocPerfTarget、ValidateSocPerfConfig、GetSocApiParamsResolveSocAscIrPerf、ResolveSocAscendCPerf4.2 软件设计 1:双维度目标选择参数(关联需求 1)
struct SocPerfTarget { std::string npu_arch; std::string soc_version; }; using SocPerfKey = std::pair<std::string, std::string>; // NpuArch、完整 SoC version。 struct SocPerfConfig { Json api_param_overrides = Json::object(); std::map<std::string, std::string> ascir_model_overrides; std::map<std::string, std::string> ascendc_model_overrides; }; using SocPerfConfigs = std::map<SocPerfKey, SocPerfConfig>;SocPerfKey是 NpuArch 与完整 SoC 的精确键,不是 profile key。配置随库交付、只读使用,不按前缀推断或解析 ini。架构形态沿用原登记:2201使用 V2,3510 / 5102 / 9201 / 9202使用 V35,未登记的3102不新增支持。架构登记与正式完整 SoC 绑定是两个独立条件。Python 从同一 CANN 编译目标取
NpuArch,通过只读requires_full_soc_version判定;仅 V35 再取SOC_VERSION,一次设置平台。C++ 显式设置二者。旧PlatformInfo.soc_ver保留 NpuArch 语义和原布局,完整 SoC 存储在 cpp 内部、沿用原锁。平台接口为
SetPlatformTarget(platform_info, soc_version)/GetPlatformTarget(npu_arch, soc_version);核心接口为ReadSocPerfTarget、ValidateSocPerfConfig、GetSocApiParams,返回af::Status。Python setter 的可选第四参数是完整 SoC。旧
set_platform三参数顺序不变;旧 setter / Reset 清除完整 SoC,新 setter 同步 UB override。包装经ReadSocPerfTarget取得本次副本,核心显式接收目标,不从平台补字段。V35 按副本的 NpuArch 查询AscirRegistry和原工厂定位基线,避免目标 A 使用平台 B 的参数。flowchart TD A[同一编译目标的 NpuArch 与完整 SoC] -->|一次设置| B[PlatformContext 双维度目标] B -->|包装读取副本| C{查询原架构登记} C -->|V2| D[原 V2 路径] C -->|V35| E{精确绑定并获取已校验配置} C -->|未登记| X[返回失败] E -->|缺名称 缺绑定 或非法配置| X E -->|成功| F[同架构历史 JSON 与目标差异] F -->|参数缓存| G[GetPerf 沿用原公式]4.3 软件设计 2:少量 API 覆盖模型(关联需求 2)
ascir_model_overridesAbsV2EvalCosts已登记的Perfkeyascendc_model_overridesGetAscendCPerfFunc注册名,如LoadV2EvalCosts已登记的AscendCPerfkey两类映射独立,保留别名和架构 tag,不把 SoC 拼进 API 名称。
GetApiPerf按显式架构创建原对象,以GetApiName()选择覆盖;只替换 Perf,原参数表、MicroPerf 和调度表指针不变。ResolveSocAscIrPerf/ResolveSocAscendCPerf以 target、API 注册名和默认函数为输入,输出所选函数,返回af::Status。default_func来自同一目标,输出沿用Perf/AscendCPerf。覆盖只选择一个已登记函数,不累计默认成本;显式关联不存在则失败。AscendC 覆盖只作用于经过GetAscendCPerfFunc的调用。原GetPerfFunc保持静态查询,注册阶段不读取平台。flowchart TD A[显式目标与规范化 API 注册名] -->|读取| B[已校验的内置配置] B -->|仅查当前 API| C{是否配置覆盖} C -->|否| D[同目标原函数] C -->|是| E{原始 EvalCosts 查询替代函数} E -->|缺失| X[返回失败 禁止默认兜底] E -->|成功| F[替代函数] D -->|执行| G[只调用所选函数一次] F -->|执行| G4.4 软件设计 3:历史参数同源与基本隔离(关联需求 3)
历史 JSON 是参数基线层:原
perf_param中的kParamV2Info原位保留,原 getter 仍返回历史表;本方案没有替代它或复制一份新参数源码。新增 MCXXXX 的 API 系数适配规则
soc_perf_config.cpp的GetBuiltinSocPerfConfigs生产分支,构造SocPerfConfig并以(NpuArch, MCXXXX)登记。参数结构为API -> model_params -> dtype pair -> 完整系数记录;参数 key 使用历史 JSON 名称Abs,不是函数覆盖注册名AbsV2。model_type,拒绝data_type_size / block_count_idx。实际 float 范围及必要除数非零校验沿用现有逻辑,负系数按公式语义处理。EnrichParamMapForModel不变。仅系数变化时两类模型覆盖映射保持为空,原公式和kParamV2Info不修改。假设已确认 MCXXXX 属于 5102,生产配置构造阶段的登记示例如下;数值仅演示,需替换为真实标定值:
SocPerfConfigs result; SocPerfConfig mc_config; mc_config.api_param_overrides["Abs"]["model_params"]["float16tofloat16"] = {{"k", 0.01F}, {"b", 22.0F}}; result.emplace(SocPerfKey{"5102", "MCXXXX"}, std::move(mc_config));正常 Python 编译自动读取完整目标;手动调用时设置二者:
ascir.utils.set_platform("5102", vector_core_num, ub_size, "MCXXXX")配置随库交付,修改后重新构建。UT/ST 验证新系数生效、未覆盖参数保持基线、默认函数不变及非法记录拒绝。测试宏使用独立配置表,公共入口测试需同步测试绑定;核心可显式注入配置。新增 SoC 的真实系数精度另做标定/RDV,不属于下文已有测试结果。
内置配置按
SocPerfKey缓存成功校验、配置副本、历史 JSON 与合成参数;首次校验与合成复用解析结果,后续入口直接命中。空差异共享解析基线,非空差异生成独立只读参数;失败不发布目标缓存。临时显式测试配置不持久缓存,避免对象地址复用。flowchart TD A[显式目标与同架构历史 JSON] -->|查内置目标| B{成功资源缓存命中} B -->|是| C[共享只读参数] B -->|否| D[校验绑定 系数及模型覆盖] D -->|失败| X[返回失败 不发布目标缓存] D -->|成功| E[复用基线解析结果并合成差异] E -->|成功后发布| C C -->|求值| F[原 dtype fallback 输入增强及公式]缓存有界,不持有 Expr、设备句柄或跨 SO 回调;核心不读取平台。
4.5 错误、兼容性与后续迁移
缺完整名称、未知架构、未登记 SoC、非法系数或显式模型缺失,在公开 codegen / ATT 入口提前失败,不跨 V2 / V35 回退。V35 公式失败不提交节点成本,Python 转为异常;历史 PGO 重试规则保留,重试目标与模型不变。
V2 原路径、历史 JSON、
ApiPerf / ModelInfo / Codegen / TilingLib旧布局和签名保持;有效 V35 空差异绑定默认成本等价,仅架构 V35 调用需补齐目标。沿用既有打包规则,测试资源不进入正式包。测试及交付证据见下文;合成测试不代表芯片精度,真实差异需 source/codegen 对照与 RDV。完整方案复用目标、绑定、稀疏映射、显式核心和 UT/ST,再扩展 context、typed 参数、全成本域、平台快照与完整错误协议。原完整版设计和计划保留,不声明 lite 已实现完整方案。
变更类型
关联的Issue
无
如何测试
一、测试用例说明
1.1 单元测试
SocPerfConfigTest36/36 通过。test_asc_codegen_compile_soc_target.py:5/5 通过。1.2 系统测试
autofuse_framework:通过,test_main与 Python 276 passed / 5 skipped。autofuse_e2e:通过,四阶段分别为 49/49、82/82、49/49、82/82。cann-graph-autofusion_9.2.0_linux-x86_64.run。二、性能验证
默认目标建模耗时约 13–14 ms/次,重复执行结果稳定;成功参数由共享只读缓存复用,核心接口不读取当前平台,默认路径无节点级 runtime 查询。内置目标校验与合成结果按目标缓存,后续函数解析仅查询当前 API 覆盖项。
核对清单
其他信息
验证方法
使用本地 CANN 与 third_party 依赖执行计划中的 C1–C9,全部通过。交付包内容已核对:正常包包含
aihac_codegen、pyautofuse与 Python 脚本;no-autofuse 包不包含 Autofuse 后端;两种包均不包含测试宏、测试配置或测试 tiling 库。注意事项
MC62CM12AA -> 5102证据,生产内置绑定表目前为空;生产 V35 请求会因缺少绑定提前失败,需确认首期清单并登记后才能正式启用。本地证据不自动视为交付授权。aihac_codegen不包含ATT_SOC_PERF_CONFIG_TEST。pyautofuse_runtime_error_tiling仅用于测试构建,不进入正式交付包。提交记录
修改文件清单
整体规模:214 个文件,2488 行新增,407 行删除。其中生产代码 14 个文件约 839 行新增 / 38 行删除,测试与构建 200 个文件约 1649 行新增 / 369 行删除。
lite 原预算为生产与测试合计 760–1000 行,文档不计入;实际新增/删除合计 2895 行,已超原预算。生产代码约 877 行不代表整体达成 1000 行目标,预算验收仍需范围复核。