资讯详情

graph-autofusion V2 节点性能建模实战:基于 af-perf-modeler 的 Cast/Reduce/Compare 算子性能公式推导指南

📅 2026/9/19 6:49:55 | 华诺云谱 👁 阅读
graph-autofusion V2 节点性能建模实战:基于 af-perf-modeler 的 Cast/Reduce/Compare 算子性能公式推导指南
graph-autofusion V2 节点性能建模实战基于 af-perf-modeler 的 Cast/Reduce/Compare 算子性能公式推导指南【免费下载链接】graph-autofusionGraph-autofusion 是一个面向昇腾Ascend芯片的轻量级、解耦式组件集合旨在通过自动融合技术加速模型执行。 目前已开源 SuperKernel 组件和 Autofuse 组件未来将持续开放更多自动融合相关模块。项目地址: https://gitcode.com/cann/graph-autofusionaf-perf-modeler是 graph-autofusionCANN 昇腾芯片自动融合组件库内置的 V2 节点性能建模 SKILL面向 Cast、Reduce、Compare 等算子的性能公式建模、ATT 性能分析、MicroAPI 成本统计以及 codegen 与性能公式对齐场景。本文以该 SKILL 的完整方法论为主线结合仓库内 codegen 实现、ATT 性能表和参数透传链路的真实源码系统讲解如何从 AscendC/MicroAPI 源码与 codegen 实际传参反推性能公式并给出可复用的建模输出模板与自查清单。一、Skill 定位graph-autofusion 的 V2 节点性能建模入口在 graph-autofusion 仓库中.claude/skills/af-perf-modeler/目录下包含两个文件README.md 与 SKILL.md。其中 README 给出了 Skill 的定位、功能范围和验证方法SKILL.md 则承载了完整的建模方法论两者共同构成 af-perf-modeler 的完整能力描述。该 Skill 覆盖三类典型工作算子性能公式建模为 Cast、Reduce、Compare 等算子建立可解释、可追溯的性能公式ATT 性能建模与 MicroAPI 成本分析基于 ATTAuto Tiling Tool自动切分工具的 VFVector Function性能管线统计repeat_time/call_count等循环执行参数并累加 MicroAPI 成本codegen 与性能公式对齐、tiling 参数透传确保 ATT 性能计算拿到的参数与 codegen 生成代码时实际传给 AscendC API 的参数一一对应。触发场景当用户提出以下诉求时即进入 af-perf-modeler 的作用域提到 Cast / Reduce / Compare 等算子的性能公式提到 ATT 性能建模、MicroAPI 成本、repeat_time/call_count提到 codegen 与性能公式对齐、tiling 参数透传。核心原则Skill 明确了一条不可妥协的建模红线性能公式必须从节点对应的 AscendC/MicroAPI 源码和 codegen 实际传参反推不能只套现有公式或凭经验估算。任何源码入口、API 参数、codegen 传参、分支含义或 MicroAPI 语义不确定的点都必须先向用户说明并询问严禁编造公式。二、建模前提先定位五类核心源码文件建模开始前必须先定位并读取以下文件SKILL.md 中列出的建模前提路径均以仓库根目录为基准建模要素仓库路径作用codegen implv2_ascir_codegen_impl.h每个 V2 节点类型对应一个AscIrCodegenImplV2子类通过GetApiName()/GetApiCallName()指明 API 与调用生成器AscendC API 源码autofuse/v35/ascendc/api_regbase/由GetApiName()指向的算子真实实现及其调用的 helpercodegen API 调用生成逻辑autofuse/v35/codegen/由GetApiCallName()指向的{ApiCallName}::Generate决定生成代码实际传给 API 的参数性能表perf_param_v2.cppkVfInstructPerfTable等性能表MicroAPI 到 latency / throughput 的映射当前性能注册/实现ascir_api_perf_v2.cpp、ascendc_regbase_perf.cpp性能公式的最终落地实现参数透传参考ascir_node_param.h 中的VectorFuncNodeParams、CastNodeParams等codegen 向 ATT 透传参数的载体以 Cast 为例在 v2_ascir_codegen_impl.h 中可以看到CastAscIrCodegenImplV2类GetApiCallName()返回CastV2ApiCallGetApiName()返回CastExtend并实现了IsVectorFunctionSupported、IsSimtScalarSupported等判定逻辑用于决定节点走 VF 融合还是 SIMT 标量路径。建模时需据此追溯到真实 API 实现。三、通用建模流程八步从源码反推性能公式1. 定位算子源码入口从v2_ascir_codegen_impl.h找到目标算子对应的GetApiName()再到autofuse/v35/ascendc/api_regbase/下查找该 API 名称的定义。读取 API 实现及其调用的 helper不只读 perf 代码因为性能公式的分支与 MicroAPI 序列完全由源码决定。若 API 名称与源码实现无法唯一对应先询问用户确认。2. 确认源码输入参数与 codegen 实际传参先分析 AscendC API 源码的函数签名确认参数含义、类型、顺序和模板参数从v2_ascir_codegen_impl.h找到目标算子的GetApiCallName()据此在autofuse/v35/codegen/下找到{ApiCallName}::Generate从Generate中分析生成代码实际传入 AscendC API 的参数包括inputs、outputs、scalar、offset、stride、mask、loop 参数、tmp buf、axis 信息等。一个必须警惕的语义陷阱codegen 的inputs/outputs是生成代码用的Tensor而 ATT 性能计算的input_shapes/output_shapes是性能建模用的TensorShapeInfo两者语义对应但不是同一对象建模时不可混用。3. 必要参数从 codegen 传递到 ATT如果性能公式需要 codegen 阶段才能确定的参数例如 loop merge 后的cal_count、outer_repeats、stride、mask mode、特殊分支标记禁止在 ATT 中凭空假设。参数传递遵循一条标准链路EnrichAscirGraphNodeParams 预注册空参数结构体 - {ApiCallName}::Generate 按实际调用填充具体值 - FillSpecificParams 提取到 NodeInfo - perf 函数读取这条链路在仓库中有完整实现预注册入口ascir_param_builder.h 声明EnrichAscirGraphNodeParams(const af::AscGraph graph)参数载体ascir_node_param.h 中AscirNodeParams::specific_params是一个std::variant可承载ReduceNodeParams、VectorFuncNodeParams、CastNodeParams、BroadcastNodeParams、CompareNodeParams、WhereNodeParams、UnaryBitWidthChangeNodeParams、TransposeNodeParams等专用结构体提取入口specific_params_builder.h 声明FillSpecificParams(const af::AscNodePtr ge_node, NodeInfo node_info)。以 Cast 为例cast_v2_api_call.cpp 中的FillCastNodeParams将output_dims、output_strides、input_strides写入CastNodeParams该结构体在 ascir_node_param.h 中定义字段与 SKILL 中强调的保存output_dims、output_strides、input_strides仅排除dst、src完全对应。透传时的两条硬性要求只预注册空结构对只能在Generate中确定的参数如ApiLoopParams、合轴后实参、实际生成分支EnrichAscirGraphNodeParams只负责预注册空结构体不要在预注册阶段猜具体值保存原始符号表达式Generate填充给 ATT 的节点参数必须使用 codegen/merge 阶段的原始符号参数如merge_info、ApiLoopParams中的 repeat、stride、count不要保存tpipe.tiler.ActualSize(...)、tpipe.tiler.Size(...)等用于生成 C 调用字符串的展开表达式因为 ATT 性能公式无法稳定识别这些 tiler 表达式。这一点在 Cast 的生成代码中有直观对照CastV2ApiCall::Generate在生成 API 调用字符串时使用tpipe.tiler.Size(param.output_second_to_last_stride)见 cast_v2_api_call.cpp而写入节点参数时则使用merge_info.merge_repeats、param.cal_count、param.output_second_to_last_stride等原始符号见同文件 L87-L106两者用途严格分离。4. 分析源码分支保持与源码if constexpr、if、模板参数、dtype 特化、dim 分支、broadcast 分支、scalar 分支、mask mode 分支一致。每个源码分支都要说明触发条件、codegen 参数来源和公式差异不允许只按 dtype 或经验简化掉源码中的关键分支。以 Cast 的 VF 支持判定为例v2_ascir_codegen_impl.h 中的IsVectorFunctionSupported就体现了典型的源码分支约束Cast 只能处理 2 倍及以内位宽变化input_dtype_size output_dtype_size * 2U时拒绝 VF 融合8 字节与 4 字节之间的转换在 MicroAPI 层要求源/目的使用双寄存器VF codegen 只生成单寄存器张量会导致设备上仅填充半数 lane真机验证约 50% mismatch因此该组合也必须拒绝 VF 融合而保留在根图走CastExtend。这些分支直接影响建模时是否将节点计入 VF 性能管线。5. 枚举 MicroAPI以源码中的每个MicroAPI::xxx或 AscendC 基础向量 API 作为最小建模粒度将其映射到perf_param_v2.cpp中的kVfInstructPerfTable类型。映射前必须查表确认不要假设表项存在找不到精确匹配时使用kPlaceholder并在代码注释中说明真实 MicroAPI 名称和暂用原因。kVfInstructPerfTable在 perf_param_v2.cpp 中定义其中既有kAdd、kSub、kCast、kCompareScalarNE、kUpdateMask、kDuplicate、kPlaceholder等指令级条目每条目给出支持的 dtype 集合及 latency、throughput 数值也有kCast的 dtype 映射表kVfInstructDtypeMappingPerfTable见 L465-L484用于处理需要按输入/输出类型分别判断的场景。6. 计算 MicroAPI 执行次数每个源码中的 MicroAPI 都应能追溯到性能公式中的一次VfPerfUtils::AddVfInstructPerf计算其最后一个参数必须来自源码循环次数或 codegen 透传参数对嵌套循环计算总次数例如outer_count * repeat_time对只在循环外执行一次的Duplicate、mask 创建、scalar 初始化等次数按源码实际执行次数建模不要误乘repeat_time如果循环次数依赖运行时数据值必须说明无法精确获取的原因并采用保守估计或要求透传参数。7. 合并同类 MicroAPI同一种 MicroAPI 类型可以只调用一次AddVfInstructPerf最后一个参数使用该 MicroAPI 在当前分支中的总执行次数合并时必须保留注释或表格追溯每一部分次数的源码位置。合并受以下约束对kPlaceholder合并键必须包含真实 MicroAPI、操作方向/模式和 dtype三者都相同才能合并即使性能表类型相同也禁止合并不同真实 MicroAPI如Not与ShiftRights、Pack与UnPackMicroAPI::DataCopy的 load 与 store 必须分开不能因为都映射为kPlaceholder而汇总kPlaceholder直接调用VfPerfUtils::AddVfInstructPerf不要增加AddPlaceholderPerf一类包装函数。8. 套用统一 cost 结构每个 MicroAPI 通过VfPerfUtils::AddVfInstructPerf(type, dtype, max_latency, all_vf_instruct_cost, count)累加内部查询 latency 和 throughputlatency 取所有 MicroAPI 的最大值throughput * count累加到all_vf_instruct_cost。最终公式固定为Expr res VfPerfUtils::GetVFHeadCost() max_latency all_vf_instruct_cost; res.Simplify(); perf.pipe_res[PipeType::AIV_VEC] res;VfPerfUtils的接口定义见 vf_perf_utils.h包括AddVfInstructPerf、GetVfInstructDtypeMappingPerf、GetVFHeadCost、GetVectorFunctionPerf等。这套公式结构在 ascendc_regbase_perf.cpp 中有真实落地res VfPerfUtils::GetVFHeadCost() max_latency all_vf_instruct_cost; perf.pipe_res[PipeType::AIV_VEC] res;。部分场景如 mask 相关路径还会用call_count整体加权res (VfPerfUtils::GetVFHeadCost() max_latency all_vf_instruct_cost) * call_count;见同文件 L205-L207这印证了repeat_time / call_count分析在 Skill 中的重要性。四、API 参数对齐原则与透传链路性能模型透传的参数必须与实际 AscendC API 调用保持一一对应排除输入、输出 Tensor 后按 API 签名的原始顺序保存其余参数不要用repeat_count、flattened_count或分支标志替换原始参数参数的维度、stride、mask、offset 和 loop 数组要保持与生成代码相同的语义粒度性能模型只在计算公式内部派生临时量以CastExtend(dst, src, output_dims, output_stride, input_stride)为例节点参数应保存output_dims、output_strides和input_strides仅排除dst、srcCastExtend节点参数中的output_dims、output_strides、input_strides应来自merge_info/ApiLoopParams的原始表达式实际生成 API 调用时可以使用tpipe.tiler但传给性能公式的节点参数不能使用 tiler 展开结果参数链路必须可追溯EnrichAscirGraphNodeParams预注册 →{ApiCallName}::Generate按实际调用填充 →FillSpecificParams提取 →NodeInfo→ perf 函数如果原始 API 参数缺失必须明确回退到 shape 信息的条件和精度影响禁止在 ATT 中凭经验重建 codegen 已经确定的参数。在仓库测试中可以看到这条链路的完整验证方式例如 test_ascir_node_params.cpp 覆盖了节点参数结构体的构建与读取ascir_reduce_test_helpers.h 展示了EnrichAscirGraphNodeParams(env.graph)与att::FillSpecificParams(env.node, node_info)的串联调用为参数透传链路提供了可执行的测试佐证。五、MicroAPI 映射规则一般情况下性能表类型为 MicroAPI 指令名增加k前缀例如MicroAPI::Add对应kAdd、MicroAPI::UpdateMask对应kUpdateMask。Skill 不维护完整的一一映射表建模时按以下顺序确认提取真实 MicroAPI 指令名以k 指令名作为候选性能表类型在perf_param_v2.cpp和常量定义中确认候选类型真实存在并确认目标 dtype 受支持不能只根据命名猜测对带模式语义的模板 API使用性能表中对应的语义后缀例如CompareScalar..., CMPMODE::NE对应kCompareScalarNE该条目确实存在于 perf_param_v2.cpp如果没有精确表项使用kPlaceholder并按真实 MicroAPI、操作方向/模式和 dtype 分开调用DataCopy的 load 与 store 即使都没有精确表项也必须分开建模并分别注释同一次 load 或 store 的LoadDist/StoreDist模式不额外重复建模如果性能表已有对应 MicroAPI 类型但暂不支持源码中的真实 dtype仍按源码真实 dtype 调用该 MicroAPI 类型不要为了命中现有表项改成中间 dtype、输出 dtype 或kPlaceholder性能表缺项应后续扩展公式必须先保持源码语义正确。MicroAPI::DataCopy的统一建模约定load 使用 input dtypestore 使用 output dtypeLoadDist、StoreDist、pack/unpack 模式只作为注释说明不因模式变化额外增加一条 DataCopy 成本。六、Placeholder 调用示例占位与可追溯性当源码 MicroAPI 在性能表中没有精确条目时占位调用必须保持每一项都可追溯到唯一真实操作下面是对比示例摘自 SKILL.md 并保留原文语义。错误做法不同真实操作或不同方向被汇总后续无法替换为精确表项。VfPerfUtils::AddVfInstructPerf(kPlaceholder, dtype, max_latency, all_vf_instruct_cost, repeat_time * 4);正确做法直接调用AddVfInstructPerf每个占位项都能追溯到唯一真实操作。// MicroAPI::DataCopy (load). VfPerfUtils::AddVfInstructPerf(kPlaceholder, input_dtype, max_latency, all_vf_instruct_cost, repeat_time); // MicroAPI::DataCopy (store). VfPerfUtils::AddVfInstructPerf(kPlaceholder, output_dtype, max_latency, all_vf_instruct_cost, repeat_time); // MicroAPI::Packuint32_t, int64_t, two calls with the same mode and dtype. VfPerfUtils::AddVfInstructPerf(kPlaceholder, int64_dtype, max_latency, all_vf_instruct_cost, repeat_time * 2); // MicroAPI::UnPackuint64_t, uint32_t. VfPerfUtils::AddVfInstructPerf(kPlaceholder, uint32_dtype, max_latency, all_vf_instruct_cost, repeat_time);注意kPlaceholder在性能表中真实存在perf_param_v2.cpplatency 与 throughput 均为 0因此占位项只是成本占位真正约束公式语义的是其唯一可追溯性。仓库中的实际 perf 实现也遵循直接调用原则例如 ascendc_regbase_perf.cpp 中对无法精确映射的 MicroAPI 直接以kPlaceholder调用AddVfInstructPerf。七、建模输出模板完成建模后按以下模板输出结构化结论SKILL.md 原文模板此处完整保留### 源码依据 - codegen impl... - API 名称... - API 源码... - API 调用生成...::{ApiCallName}::Generate - 性能表.../perf_param_v2.cpp - 当前 perf 实现.../ascendc_regbase_perf.cpp ### 参数来源 | 源码参数 | codegen 传参来源 | ATT 是否可直接获取 | 处理方式 | | --- | --- | --- | --- | | dst | outputs[0] | 是/否 | ... | | src | inputs[0] | 是/否 | ... | | loop_param | ApiLoopParams | 否 | 需通过节点参数透传 | ### 分支分析 - 分支 A触发条件参数来源源码行公式差异 - 分支 B触发条件参数来源源码行公式差异 ### MicroAPI 计数 | MicroAPI | perf 类型 | 执行次数 | dtype | 说明 | | --- | --- | --- | --- | --- | ### 公式 cpp Expr max_latency CreateExpr(0); Expr all_vf_instruct_cost CreateExpr(0); // AddVfInstructPerf(...) Expr res VfPerfUtils::GetVFHeadCost() max_latency all_vf_instruct_cost; ### 不确定点 - 无或列出需要用户确认/源码待确认的问题。八、常见错误自查表建模中最容易犯的错误集中在公式与源码脱节和参数来源不清晰两类SKILL.md 给出的错误对照表完整如下错误正确做法直接复述现有 perf 公式先读 API 源码和 codegen 传参再解释现有公式是否简化只看input_shapes/output_shapes同时看{ApiCallName}::Generate确认实际传入 API 的参数需要 loop 参数却在 ATT 中猜测通过节点参数从 codegen 透传或说明无法精确获取Generate 才能确定的参数却要求EnrichAscirGraphNodeParams计算具体值EnrichAscirGraphNodeParams只预注册空结构Generate填具体值性能函数只能访问NodeInfo却让 ATT 直接读 Node补FillSpecificParams把节点参数提取到NodeInfo只写入节点参数但 ATT 读取路径不明确明确链路预注册空结构 → Generate 填值 → FillSpecificParams → NodeInfo → perf给 ATT 的节点参数保存tpipe.tiler.Size/ActualSize展开值保存merge_info/ApiLoopParams原始符号表达式tiler 表达式只用于生成 C 调用字符串忽略if constexpr或 scalar/mask 分支每个源码分支单独列触发条件和计数把所有 MicroAPI 都乘repeat_time按源码实际循环层级计算次数找不到性能表项就跳过使用kPlaceholder并注释真实 MicroAPI性能表暂不支持真实 dtype 就换成支持的 dtype保持源码真实 MicroAPI 类型和 dtype后续扩展性能表多个同类 MicroAPI 重复调用多次合并为一次AddVfInstructPerf次数求和把不同真实 MicroAPI 汇总到一个kPlaceholder按真实 MicroAPI、方向/模式和 dtype 分开调用把DataCopyload 和 store 合并load 与 store 分开调用并分别注释因DataCopy的 pack/unpack 模式再额外补一条成本DataCopy 只按 load/store 建模dtype 分别使用 input/output用辅助函数包装kPlaceholder直接调用VfPerfUtils::AddVfInstructPerf(kPlaceholder, ...)UpdateMask使用kPlaceholder使用性能表已有的kUpdateMask未说明不确定点不确定时先提问或列入不确定点九、验证要求与验证方法公式完成后的逐项检查清单完成公式后至少检查以下事项来自 SKILL.md 的验证要求逐条保留API 源码入口能从GetApiName()追溯API 调用参数能从{ApiCallName}::Generate追溯ATT 使用的额外参数若来自 codegen已通过节点参数传递若性能函数只能访问NodeInfo必须确认EnrichAscirGraphNodeParams已预注册空结构、Generate已填值、FillSpecificParams已提取到NodeInfo公式中的每个AddVfInstructPerf都能追溯到源码 MicroAPI每个循环次数都能追溯到源码循环、codegen 参数或明确的保守估计每个 MicroAPI 类型都在perf_param_v2.cpp中存在不存在时已用kPlaceholder并说明每个kPlaceholder都有唯一的真实 MicroAPI、操作方向/模式和 dtypeload/store 及不同真实类型未合并kPlaceholder均直接调用VfPerfUtils::AddVfInstructPerf未增加包装函数MicroAPI::UpdateMask使用kUpdateMask最终 cost 使用VfPerfUtils::GetVFHeadCost() max_latency all_vf_instruct_cost。Skill 生效验证在 opencode 中输入以下指令验证 Skill 是否生效README 提供的官方验证方法计算cast算子的性能公式分析compare算子性能公式十、深入源码与测试进一步学习路径如果希望进一步验证本 Skill 方法论在仓库中的落地情况可以按以下路径继续阅读codegen 侧v2_ascir_codegen_impl.h 定义全部 V2 节点的 codegen 实现含GetApiName/GetApiCallNamecast_v2_api_call.cpp 展示CastV2ApiCall::Generate如何填充CastNodeParamsreg_api_call/ 目录下还有compare_v2_api_call.cpp、unary_bitwidth_change_api_call_v2.cpp、reg_load_api_call.cpp等同类实现ATT 侧ascendc_regbase_perf.cpp 与 ascir_reduce_api_perf_v2.cpp 是性能公式的落地实现perf_param_v2.cpp 是性能表数据源测试侧test_ascir_perf_v2.cpp、test_reduce_min_max_api_perf_v2.cpp 覆盖 ATT 性能公式test_codegen_cast_reg_api_call.cpp 与 test_codegen_compare_reg_api_call.cpp 覆盖 codegen 传参test_ascir_node_params.cpp 覆盖节点参数结构体。结语af-perf-modeler 提供了一套源码 → codegen 传参 → 节点参数透传 → ATT 性能公式全链路可追溯的 V2 节点建模方法论。对开发者而言掌握这套流程意味着面对任意 V2 算子都能从GetApiName()/GetApiCallName()出发沿EnrichAscirGraphNodeParams→Generate→FillSpecificParams→NodeInfo→ perf 函数的链路推导出与真实生成代码语义一致的性能公式而不是复制粘贴一份无法解释的既有公式。这套方法同时是 codegen、ATT 与性能模型三方对齐的工程规范值得在新增算子建模或性能问题定位时直接复用。【免费下载链接】graph-autofusionGraph-autofusion 是一个面向昇腾Ascend芯片的轻量级、解耦式组件集合旨在通过自动融合技术加速模型执行。 目前已开源 SuperKernel 组件和 Autofuse 组件未来将持续开放更多自动融合相关模块。项目地址: https://gitcode.com/cann/graph-autofusion创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。