
PyPTO-Gym 的 HF-NPU 端到端工作流从 HuggingFace 模型卡到昇腾 NPU 的 E2E 吞吐测量【免费下载链接】pypto-gymPyPTO-Gym 是基于 PyPTO 编程框架构建的算子与模型样例仓库项目地址: https://gitcode.com/cann/pypto-gymPyPTO-Gym 仓库内置了一套名为hf-npu-e2e-workflow的编排工作流负责把一个 HuggingFace 模型卡 ID 一路跑到昇腾 NPU 上、并给出可对比的端到端E2E吞吐数字模型下载 → 运行时补丁auto_map 仓内 modeling→ NPU 冒烟运行 → eager / NPUGraph 双路测速只有确实需要新融合算子时才在最后一步调用pypto-fused-op-integration。读完本文你可以复制粘贴地完成上述 5 个步骤的全部命令、理解 NPUGraph 图捕获在昇腾 NPU 上的典型报错107025 / 107027 / 107030 / 507015及其修复手段并知道何时该停下来做算子融合、何时不该做。工作流总览每一步都可独立跳过该工作流的定位是orchestration workflow编排流程而非 how-to 教程。它把 PyPTO-Gym 中已有的资产下载脚本、运行时补丁脚本、测速 harness、融合算子集成 skill串成一条流水线关键设计原则是不是每次运行都需要算子融合因此融合被放在最后且是可选步骤。目标需要执行的步骤只想在 NPU 上跑通并测速1 → 2 → 3 → 4下载 → 补丁 → 运行 → 测速无融合还想看融合 kernel 的收益 5调用pypto-fused-op-integration→ 重新执行 4工作流的“新增资产层”即本流程自身拥有、不复用其他 skill 的部分包括bench_npu.py — 通用的 eager / graph 双路 E2E 测速脚本内置图捕获自动缓解措施与 ACL 错误码诊断npu_capture.py — 图捕获安全原语apply_capture_mitigations、CaptureCache、capture_and_replay、explain_capture_errornpu-run-and-measure.md — regime 定义、三路对比、NPUGraph 捕获坑点表错误 → 原因 → 修复、捕获安全配方与测量流程。相应地工作流不拥有避免重复的能力是HF 入网细节由步骤 1–2 的两个脚本承担旧版migrate-huggingface-to-npuskill 已被这两个脚本取代、算子融合方法论与USE_PTO_OP开关 / sys.modules 注入由 pypto-fused-op-integration 承担本流程只负责“调用它 测结果”。步骤 1下载模型 —download_hf_model.pypython modeling/transformers/download_hf_model.py --model-id org/repo --output-dir DIR # 可选[--revision R] [--token T] [--allow-pattern P] [--ignore-pattern P]参数含义对应 download_hf_model.py 中parse_args的定义参数说明--model-idHuggingFace 模型卡 ID必填如org/repo--output-dir本地模型目录必填脚本会自动makedirs--revision可选指定模型 revision--token可选HuggingFace 访问令牌--allow-pattern/--ignore-pattern可多次传入的包含 / 排除模式用于只拉权重或排除大文件实现要点底层是huggingface_hub.snapshot_download支持断点续传脚本会对旧版本snapshot_download自动做token→use_auth_token的参数回退见 download_hf_model.py。需要镜像源时设置HF_ENDPOINThttps://hf-mirror.com即可。下载完成后脚本会打印export MODEL_PATHpath供后续步骤直接引用。步骤 2运行时补丁auto_map 仓内 modeling—runtime_patch.py# 预置模型族: gemma4_31b_it | llada2_moe | minimax_m27 | minimax_m3 python modeling/transformers/runtime_patch.py --model-family FAMILY --model-path DIR # 新模型: --auto-map AutoConfigcore.configuration_X.XConfig --copy core/modeling_X.pysrc目的把 HuggingFace 下载的模型目录“钉”到PyPTO-Gym 仓内维护的 modeling 代码上使模型加载不再依赖 HF 缓存或远端modeling_*.pytrust_remote_code拉取远程代码存在供应链与可用性风险。runtime_patch.py 的四种预置家族PRESET_SPECS见 源码分别映射到仓内现成的 modeling / configuration 实现familyauto_map 目标仓内源文件gemma4_31b_itconfiguration_gemma4.Gemma4Config等gemma4_31b_it/llada2_moemodeling_llada2_moe.LLaDA2MoeModelLMllada2_moe/minimax_m27modeling_minimax_m27.MiniMaxM2ForCausalLMminimax_m27/minimax_m3modeling_minimax_m3.MiniMaxM3ForCausalLMminimax_m3/对仓内没有现成 modeling 的新模型使用自定义模式--auto-map KEYVALUE与--copy DESTSOURCE可各传多次python modeling/transformers/runtime_patch.py \ --model-path /path/to/model \ --auto-map AutoConfigconfiguration_X.XConfig \ --auto-map AutoModelForCausalLMmodeling_X.XForCausalLM \ --copy modeling_X.py/path/to/modeling_X.py \ --copy configuration_X.py/path/to/configuration_X.py脚本实际做了四件事patch_model_dir实现见 源码将预置的auto_map写入模型目录的config.json原文件先备份为config.json.pypto_orig把仓内 modeling / configuration 文件拷贝进模型目录原文件同样备份为*.pypto_orig清理~/.cache/huggingface/modules/transformers_modules下与模型名相关的旧缓存模块防止 HF 使用缓存里的旧代码打印export MODEL_PATHpath。此外还支持--output-dir生成一个非破坏性 overlay 目录其余文件用符号链接指向原模型目录仅替换 config 与 modeling以及--source-root指定提供补丁源文件的 pypto-gym 检出目录、--force覆盖非空输出目录。步骤 3NPU 冒烟运行迁移门禁这是整个工作流的“迁移门禁”migration gateeager 都跑不通就不要进入测速阶段。做法用local_files_onlyTrue加载模型杜绝回源 HF仅当模型确实需要时才加trust_remote_code生成少量 token确认 NPU 上输出的是连贯文本而非乱码。仓内每个适配过的模型目录都带了这样的推理脚本可直接作为冒烟入口例如 ask_Qwen3.5-9B.py它通过--model-path或环境变量MODEL_PATH定位权重--device指定卡号以local_files_onlyTrue, trust_remote_codeTrue加载后调用generate其 PyPTO 注入sys.modules注入在transformers导入之前USE_PTO_*开关在模型上卡之后才打开恰好演示了步骤 5 融合集成的正确时序。步骤 4E2E 测速 —bench_npu.pypython scripts/bench_npu.py \ --model-path DIR --device 0 --regime decode --gen 128 --arms eager,graph4.1 先定 regime三种“tok/s”不可互相比较参考文档 npu-run-and-measure.md 强调同一个模型会同时存在三种都被叫作“tok/s”的数字每个模型只选一个 regime 并明确标注regimetok/s 公式度量对象适用场景prefillseq_len / single_forward_time输入并行前向吞吐无 KV cache大模型 / 多 die / FP8 权重流式加载等 decode 循环不现实的场景decode (AR)N / decode_loop_timeseq1 KV cacheN 步真实自回归出词速度单 die 自回归 LMdiffusion-generategen_positions / denoising_timeW×S 个去噪前向扩散 LM 出词吞吐块扩散 LM没有 AR decode 可跑经验法则prefill 的 tok/s 远大于 decode一次大并行前向 vs 串行内存受限步骤——不要把它们放进同一列而不标注 regime。4.2 三条对比 armeager— 原生 HF forward /model.generate作为基线。默认加载attn_implementationeagerSDPA 是最快也最“慷慨”的非图注意力的公平基线而它的融合 kernel 恰好是图捕获的拦路虎见 4.4。NPU-friendly (graph)— 静态 shape 的torch.npu.NPUGraph捕获后 replayMoE 场景即“静态路由下的向量化 expert 循环”vecgraph。PyPTOgraph— PyPTO 融合 kernelgrouped GEMM / softmax / GQA在同一份捕获下的表现由步骤 5 接线后自动得到。报告时只报告同机比值绝对 tok/s 依赖节点配置跨节点不可复现只有比值有意义。4.3bench_npu.py参数与测量细节完整参数表对应 parse_args参数默认值说明--model-path必填本地模型目录步骤 2 的输出--device0NPU 卡号同时写入TILE_FWK_DEVICE_ID--regimedecodeprefill或decode--seq16prefill / graph forward 的序列长度--gen128decode要生成的 token 数--armseager,graph逗号分隔的路径选择--warmup2预热次数吸收 JIT 首编与首次捕获--iters3计时轮数取 best-of-N--trust-remote-codeoff需要时才开启--report-fileNone结果 JSON 落盘路径测量实现源码best-of-N先跑warmup次吸收 PyPTO 首次编译、首次图捕获再取iters次中最快的min()结果计时边界time_forward/time_generate前后各一次torch.npu.synchronize()保证测的是 NPU 完成时间而非发射时间eager armprefill 用随机input_ids (1, seq)跑单次 forwardtok/s seq / best_forward_sdecode 用 8 个 prompt token 跑贪心generate(max_new_tokensgen)tok/s gen / best_loop_sgraph arm固定 shape 捕获model.forward(..., use_cacheFalse).logitsuse_cacheFalse避开 DynamicCache 的主机侧操作先调用apply_capture_mitigations中性化 rotary 主机同步与 mask 准备再capture_and_replay20 次 replay 取均值tok/s window / best_replay_s内存与环境结束时记录torch.npu.max_memory_allocated峰值启动时自动os.environ.setdefault(PYTORCH_NPU_ALLOC_CONF, expandable_segments:True)为捕获预热的显存尖峰做防碎片化见 main。测量流程要点始终记录 peak HBM 与 reserved——若 reserved 随迭代增长就是动态 shape 工作区泄漏的信号修复手段是固定 shape 或按 N 分桶 padding。4.4 NPUGraph 捕获坑点表错误 → 原因 → 修复NPUGraph 捕获会在任何做主机同步或**使用侧流side stream**的算子上中止症状统一表现为capture_end/replay 处难懂的 ACL 报错。以下是工作流总结的坑点表源自 gemma4 decode 捕获、llada2 扩散块捕获、minimax_m27 静态路由 grouped GEMM 的实测症状原因修复107025出现在capture_end默认SDPA的 NPU 融合 kernel 运行在侧流上以attn_implementationeager加载107025/107030捕获期间 H2D_prepare_4d_causal_attention_mask_for_sdpa做主机侧torch.all(mask1)同步传入预构建的加性 mask并 patch prepare 函数直接返回它107025rotary embed 使用torch.autocastdynamic_rope_update主机侧 seq-len 检查position 固定 →一次性预计算 cos/sin作为常量注入替换rotary.forward107027copy-stream 同步/[ArgSort] ... AiCpu算子跑在 copy/侧流上——最常见是 MoE 的argsort(int64)落在AICPU上任何侧流算子滑窗 mask 构建、qk-norm 路径都算MoE →静态路由固定分配、预计算cumsum捕获下只执行index_select 设备侧 GEMM否则二分定位107030捕获期间 H2DDynamicCache主机操作 / cache 长度推进捕获安全的 KV cache固定槽位index_copy_无主机操作replay 之间对写槽位张量做原地推进aicore 507015replay/runPyPTOgrouped_gemm收到增长/动态shape捕获前固定 shape单一固定 block或将 N 分桶 padding 到少数离散尺寸npu_capture.py把这张表直接编码为CAPTURE_GOTCHAS字典见 源码捕获失败时explain_capture_error会按错误码匹配打印“[capture 107027] cause: ... / fix: ...”形式的可执行诊断bench_npu.py的 graph arm 在捕获失败时即走这条路径源码。4.5 捕获安全配方Capture-safe recipenpu_capture.py提供的原语与通用步骤加载attn_implementationeager侧流问题无法事后补救必须加载时就定绕过model.forward的 mask/rope 机制apply_capture_mitigations(model, window, device)会a将 modeling 模块的_prepare_4d_causal_attention_mask_for_sdpa替换为恒等透传源码b定位 rotary 模块依据inv_freqrope_init_fn属性以固定position_ids预计算一次cos/sin并把rotary.forward替换为返回缓存常量返回(cos, sin, zero_mask, position_ids)供手工驱动 decoder stackMoE→ 安装静态路由每个 token 分给前top_k个 expertcumsum预计算计算量不变同样 N×K 行过 GEMM只是把分配变成确定性的decode regime→ 使用CaptureCache预分配keys/values为(batch, nkv, maxlen, head_dim)固定张量update只做index_copy_(2, write_pos, ...)replay 之间对write_pos张量原地1源码全程无主机操作捕获与计时capture_and_replay先在侧流跑 3 次 warmup再torch.npu.NPUGraph()捕获2 次 warmup replay 后连续 replayn_replays次同步计时返回每 replay 平均秒数源码二分定位失败bisect_capture按embednorm→attention→完整层逐级尝试捕获从 OK 翻成 FAIL 的那一级就锁定了罪魁祸首算子SDPA 侧流问题正是这样被发现的见 源码。步骤 5可选融合 — 调用pypto-fused-op-integration只有当模型确实需要新的融合 kernelgrouped GEMM / attention 等时才进入此步。工作流本身不重新实现融合方法论而是把 golden 生成 → 算子开发 → 精度对比 →集成USE_PTO_OP开关 sys.modules注入整个流程交给 pypto-fused-op-integration。该 kernel 被接线并打开开关后重跑步骤 4--arms eager,graphgraph arm 此时捕获的就是 PyPTO 加速后的 forward得到pyptograph数字。调用时需在工作流侧应用两条覆盖规则不要改那个 skill 本身跳过它的过期 onboarding 步骤其下载步骤裸snapshot_download与代码部署步骤手工拷贝core/fix_imports.py 手写auto_map已由本工作流的步骤 1–2download_hf_model.pyruntime_patch.py取代直接跳过版本钉扎是环境特异的其pip install torch2.7.1 torch-npu2.7.1只是示例环境的事实。持久规则是“torch 版本 torch_npu 版本并匹配本机 CANN”查你已装 CANN 对应的torch_npu发布版本再把torch钉到完全相同的版本号——不要照抄固定数字。Regime 选择速查与适用边界按模型形态快速决策源自参考文档 §6多 die / 100B / FP8 权重流式 → prefill decode 循环不现实 单 die 自回归 LM → decode 真实出词速度 块扩散 LMLLaDA 类 → diffusion-generate 稠密模型无 expert → PyPTO 没有 MoE GEMM 可融合 pyptograph ≈ graphgraph 仍有去除 launch 开销的收益grouped-GEMM 的 收益只出现在稀疏 MoE 模型上一个重要的预期管理稠密模型上 PyPTO 融合通常不带来 grouped-GEMM 级别的收益——此时grapharm 相对eager的收益主要来自 launch 开销消除只有在稀疏 MoE 模型上grouped GEMM 融合才有独立的性能看点。小结资产与边界资产路径角色下载脚本modeling/transformers/download_hf_model.py步骤 1断点续传快照下载运行时补丁modeling/transformers/runtime_patch.py步骤 2auto_map 仓内 modeling测速 harnessscripts/bench_npu.py步骤 4eager/graph 双路 JSON 报告捕获原语scripts/npu_capture.py步骤 4 支撑坑点表 安全原语 二分诊断测速方法论references/npu-run-and-measure.mdregime / 三路 / 坑点表 / 测量流程融合集成pypto-fused-op-integration/SKILL.md步骤 5仅按需调用这条流水线的所有命令都以MODEL_PATH环境变量串联每一步结束都会打印export MODEL_PATHpath下一步直接消费它。按“定 regime → 跑冒烟 → 双路测速 → 按需融合 → 重测”的顺序执行即可把一个 HF 模型卡变成一份可对比、可复现同机比值意义上的昇腾 NPU E2E 吞吐报告。【免费下载链接】pypto-gymPyPTO-Gym 是基于 PyPTO 编程框架构建的算子与模型样例仓库项目地址: https://gitcode.com/cann/pypto-gym创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考