恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
CANN NPU 多流与控核 API 路由指南:Ascend IR/GE 与 npugraph_ex 双路径选型与实战
首页
资讯中心
/
CANN NPU 多流与控核 API 路由指南:Ascend IR/GE 与 npugraph_ex 双路径选型与实战
CANN NPU 多流与控核 API 路由指南:Ascend IR/GE 与 npugraph_ex 双路径选型与实战
发布时间:2026/9/18 13:46:49
CANN NPU 多流与控核 API 路由指南Ascend IR/GE 与 npugraph_ex 双路径选型与实战【免费下载链接】cann-recipes-infer本项目针对LLM与多模态模型推理业务中的典型模型、加速算法提供基于CANN平台的优化样例项目地址: https://gitcode.com/cann/cann-recipes-infer本文是 CANN 推理仓库cann-recipes-infer中 LLM / 多模态模型推理优化的多流技术速查指南核心解决一个高频问题面对一个需要多流multi-stream、双流dual-stream、stream overlap 或控核limit_core_num优化的模型到底该选哪套 API文章基于本仓库多流技能包的 API 路由文档给出执行路径判定、双路径 API 对照、问题类型路由表和推荐决策顺序并附上仓库内真实案例与源码佐证读者读完后可以独立完成先判路径 → 再选 API → 切流/同步/控核 → 验证 overlap的完整实施闭环。为什么需要 API 路由两条执行路径不能混用NPU 推理优化中多流并不是一套 API 打天下。根据模型当前走的是eager / torch.compile还是TorchAir 图编译多流表达、时序控制和核资源限制的接口完全不同。本仓库 api-routing.md 的核心任务就是把执行路径 / 问题类型映射到上游文档和推荐 API避免把两条路径的接口混写进同一套实现。先记住两条主路径的定界方法见 SKILL.md 的执行路径定界一节执行路径定界写法多流文档入口控核文档入口Ascend IR / GE 图模式torchair.CompilerConfig()torchair.get_npu_backend()resources/ascend_ir_multi_stream.mdresources/ascend_ir_limit_cores.mdnpugraph_ex / aclgraphtorch.compile(..., backendnpugraph_ex)resources/npugraph_ex_multi_stream.mdresources/npugraph_ex_limit_cores.md术语辨析上游 torchair 文档中「Ascend IR」和「GE 图模式」指同一条路径只是分别从 IR 侧和执行侧描述——通过torchair.CompilerConfig(modemax-autotune)把 PyTorch FX 图转成 Ascend IR再由 GEGraph Engine编译执行。所以 multi_streamAscend IR文档里写仅适用于 GE 图模式并不矛盾。路径一Ascend IR / GE 图模式的多流与控核适用场景与核心约束本路径多流主要面向Ascend IR 图内资源并发max-autotune 模式尤其针对Cube 计算资源未完全使用的场景。官方表述为「Ascend IR 图内资源并发」把原本需要串行的多个算子分发到不同 stream形成计算与计算、计算与通信的 overlap降低整体耗时。关键约束来自 resources/ascend_ir_multi_stream.md仅适用于 GE 图模式场景torchair.CompilerConfig()torchair.get_npu_backend()。Cube 已吃满时不要默认开多流可能因额外调度导致原计算性能劣化含 Cube 计算的场景开启后效益往往优于纯 Vector 场景。静态 shape 下不要和单流执行功能enable_single_stream混用也不推荐在 SuperKernel 内手搓多流如需在 SuperKernel 内分流使用 stream-fusion 编译选项。动态 shape 默认单流通过环境变量开启多流且该功能优先级低于显式多流表达export ENABLE_DYNAMIC_SHAPE_MULTI_STREAM1切流 APInpu_stream_switchGE 图模式优先接口是torchair.scope.npu_stream_switch用 with 语句块把块内算子切到指定stream_tag流with torchair.scope.npu_stream_switch(stream_tag: str, stream_priority: int 0, enable_inner_parallel: bool True):参数语义stream_tag需要切换到的流的标签相同标签代表相同流由用户控制stream_priority流的优先级Runtime 并发时优先给高优先级流分配核资源当前版本用默认值 0 即可enable_inner_parallel是否使能该流内算子按 GE 原有并发策略分流默认开启。注意 with-block 不是硬边界SKILL.md 核心原则默认enable_inner_parallelTrue时GE 仍可在 block 内外做调度——可能把 block 内小算子Cast / Reshape / Swish挪到主流也可能把 block 外被 block 内 tensor 间接依赖的轻量预计算典型如silu(z) Swish(Cast(z))拉到主流形成 barrier。源码层级 ≠ 物理层级切流后必须用 profiler 验证物理布局。时序控制 APInpu_wait_tensortorchair.scope.npu_wait_tensor(self, dependency)用于显式控制跨流时序指定算子等待某个 tensor 依赖执行完再执行。两条流之间存在控制依赖、但后继不直接吃前驱输出 tensor 的场景优先用它。官方示例节选自 resources/ascend_ir_multi_stream.md图中虚线控制边即显式跨流数据依赖同步import torch, os import torch_npu import torchair as tng from torchair.configs.compiler_config import CompilerConfig class Model(torch.nn.Module): def forward(self, in1, in2, in3, in4): add_result torch.add(in1, in2) with tng.scope.npu_stream_switch(1): # torch.mm(mm_result) 等待 torch.add(add_result) 执行完再执行 tng.scope.npu_wait_tensor(in4, add_result) mm_result torch.mm(in3, in4) mm1 torch.mm(in3, in4) with tng.scope.npu_stream_switch(2): tng.scope.npu_wait_tensor(in4, mm_result) add2 torch.add(in3, in4) return add_result, mm_result, mm1, add2 model Model() config CompilerConfig() config.debug.graph_dump.type pbtxt npu_backend tng.get_npu_backend(compiler_configconfig) model torch.compile(model, backendnpu_backend, dynamicFalse, fullgraphTrue)控核算子级 vs 全局级GE 图模式控核分两层resources/ascend_ir_limit_cores.md算子级优先级更高torchair.scope.limit_core_num(op_aicore_num, op_vectorcore_num)with 块内算子按指定核数运行op_aicore_num取值[1, max_aicore]op_vectorcore_num取值[1, max_vectorcore]仅存在 AI Core 无 Vector Core 的产品只支持 0。全局级config.ge_config.aicore_num ${aicore}|${vector}字符串类型形如24|100${aicore_num}与${vectorcore_num}必须用|分隔。算子级优先级高于全局级实际运行核数可能少于配置的最大核数且不能超过 AI 处理器允许的最大核数可查CANN软件安装目录/arch-linux/data/platform_config/soc_version.ini中的ai_core_cnt/cube_core_cnt/vector_core_cnt。配置结果可通过 graph dump 确认config.debug.graph_dump.type txt在图结构attr属性中查看生效的算子级核数key 分别为_op_aicore_num和_op_vectorcore_num。路径二npugraph_ex / aclgraph 的多流与控核适用场景与 API 家族npugraph_ex 路径的多流主要面向aclgraph 间资源并发同样针对 Cube 资源未完全使用的场景。官方路径围绕显式 stream Event 生命周期管理展开核心 API 家族是切流 scopewith torch.npu.stream(stream)其中stream torch.npu.Stream()时序控制event torch.npu.Event()event.record()默认在当前流上记录event.wait(stream)指定流上等待或 Stream 侧record_event/wait_event/wait_stream生命周期tensor.record_stream(other_stream)官方示例节选自 resources/npugraph_ex_multi_stream.mdimport torch import torch_npu class Model(torch.nn.Module): def forward(self, in1, in2, in3, in4): stream1 torch.npu.Stream() stream2 torch.npu.Stream() event1 torch.npu.Event() event2 torch.npu.Event() add_result torch.add(in1, in2) B in3 in4 event1.record() # 默认在 current stream 上记录 with torch.npu.stream(stream1): event1.wait(stream1) # stream1 上的任务等待 record 执行完毕 mm_result torch.mm(B, in4) event2.record() B.record_stream(stream1) # 延长 B 在 stream1 上使用的内存生命周期 mm1 torch.mm(in3, in4) with torch.npu.stream(stream2): event2.wait(stream2) add2 torch.add(in3, in4) return add_result, mm_result, mm1, add2 model Model().to(npu) model torch.compile(model, backendnpugraph_ex, fullgraphFalse, dynamicFalse)生命周期判断是硬性要求record_stream只在短生命周期 tensor 会被其他流继续使用时才需要补模型权重、常驻 cache 这类长生命周期对象一般不需要。只在 aclgraph / eager / capture 阶段补不要对权重对象滥用。在torch.compile(fullgraphTrue, dynamicTrue)下 dynamo 拦截 Stream / Event 对象缺as_proxy()时改用torch.npu.npugraph_ex.scope.npu_stream_switch(tag)或torch.npu.npugraph_ex.scope.npu_tagged_event_record/npu_tagged_event_wait这套 string-tag / tagged-event 接口。控核Stream 级仅限 Ascend C 算子npugraph_ex 提供Stream 级核数配置resources/npugraph_ex_limit_cores.mdwith torch.npu.npugraph_ex.scope.limit_core_num(op_aicore_num: int, op_vectorcore_num: int):与 GE 路径的控核约束差异极大不要混着理解仅 Ascend C 算子支持控核非 Ascend C 算子包括非 AI Vector 控核的通信类算子暂不支持。micro-batch 多流场景若夹杂不支持控核的算子收益可能下降严重时可能卡死不推荐使用。CANN ≤ 8.5.0 时静态 kernel 编译与控核同时开启的情况下优先保留控核功能静态 kernel 编译失效。不支持多线程并发设置同一条流上的控核数无法保证算子执行时的控核生效值。配置结果优先通过Ascend PyTorch Profiler推荐torch_npu.profiler.profile接口采集在kernel_details.csv中查看AI Core / AI Vector 算子核数在Block Num列Mix Core 算子的从加速器核数在Mix Block Num列。第一步先判执行路径动手前先确定当前代码走哪条路径再选一套主 API不要混着写。路由表如下对应 api-routing.md当前场景推荐 API 风格首选 API先读文档eager / patch 改造显式流对象torch.npu.Stream()、Stream.record_event()、Stream.wait_event()、Stream.wait_stream()、tensor.record_stream()先看仓库案例需对齐显式 stream / event 语义时参考 npugraph_ex_multi_stream.md 中 Eager 模式说明ge_graph/ TorchAir 图内多流图内 scopetorchair.scope.npu_stream_switch、torchair.scope.npu_wait_tensor先读 ascend_ir_multi_stream.md需控核时再读 ascend_ir_limit_cores.mdnpugraph_ex/ aclgraph显式 stream Eventtorch.npu.Stream()、torch.npu.stream()、torch.npu.Event()Event.record()/Event.wait(stream)、tensor.record_stream()先读 npugraph_ex_multi_stream.md需控核时再读 npugraph_ex_limit_cores.md第二步再判问题类型确定执行路径后按问题类型路由到具体 API对应 api-routing.md 的问题类型表问题类型推荐 API什么时候用注意事项把一段计算切到副流torch.npu.stream(stream)eager / npugraph_ex或torchair.scope.npu_stream_switchGE 图模式已确认两段路径没有直接data依赖只在后面汇合先明确汇合点再决定补EventStream.wait_stream、Event.wait(stream)还是npu_wait_tensor显式控制跨流时序GE 图模式优先torchair.scope.npu_wait_tensor显式 stream 路径优先Event.record()/Event.wait(stream)已有 tagged event 风格时沿用npu_record_tagged_stream/npu_tagged_event_wait两条流之间存在控制依赖但后继不直接吃前驱输出 tensor不要为了统一风格强行改写已有 tagged event 代码延长 tensor 生命周期tensor.record_stream(other_stream)短生命周期 tensor 会在别的流继续使用主要看 aclgraph / eager / capture 阶段权重等长生命周期对象一般不需要overlap 成立但一条流明显拖尾limit_core_numGE 路径torchair.scope.limit_core_numnpugraph_ex 路径torch.npu.npugraph_ex.scope.limit_core_num已看到两条流资源争抢或一条流长期占满 CoreGE 是算子级 全局级算子级优先npugraph_ex 是 Stream 级且仅对 Ascend C 算子生效查看或设置 stream 资源限制torch_npu.get_stream_limit/torch_npu.set_stream_limit已进入控核或 stream 资源调优阶段这不是第一手多流 API通常在资源调优阶段再用扩大计算窗口、掩盖权重搬运torch_npu.npu_prefetchoverlap 正确但仍有访存或带宽空洞可被前序轻算子掩盖只在前序算子不明显抢带宽时使用常和多流 控核联动关于 tagged event 的命名空间高频踩坑点npu_record_tagged_stream/npu_tagged_event_record/npu_tagged_event_wait这类 tagged event 同步原语GE 路径在torchair.ops.*npugraph_ex 路径在torch.npu.npugraph_ex.scope.*而GE 路径的切流 /npu_wait_tensor才在torchair.scope.*是两个不同命名空间不要弄混。优先跟随仓库现有案例代码如 moe-shared-expert-dual-stream.md 中tng.ops.*tng即torchair不要脱离上下文自己猜语义。推荐决策顺序按 api-routing.md 的推荐多流优化遵循四步决策顺序先确定当前是eager / patch还是graph / TorchAir。先选一套主 API 路径不要混着写。先把依赖和同步做对再确认是否真的有 overlap。只有在overlap 正确但拖尾明显时才进入控核、stream limit、预取调优。这也与 SKILL.md 的实现节奏一致先做最小可验证 overlap只改一个明确并行点先补同步再扩大并行窗口始终保留原路径和 enable 开关overlap 成立后再评估控核放大改动前做一次 warm-run 验证profile 至少跑 5 次丢掉前 2-3 次 cold-start 取中位数。常见误区api-routing.md 明确列出的五大误区是 review 多流改造时最先要查的点不要在 eager 路径里照搬 TorchAir 的 tagged event 风格。不要把limit_core_num当成默认步骤它只解决资源分配问题不解决依赖错误。不要用npu_prefetch掩盖一个本来就不该并行的链路先证明链路没有错误依赖。不要在 aclgraph / eager 路径里省略record_stream()的生命周期判断只切流不管内存同样会出错。不要混抄案例先确定当前模型走哪条执行模式再选一套主 API 路径不要把 eager 和 graph 风格混着套。仓库案例佐证从路由表到落地实现API 路由表之外本仓库沉淀了一批真实模型案例可作为选型后的参照实现快速选型表见 examples/README.md。MoE 共享专家双流moe-shared-expert-dual-stream.md代表实现 DeepSeek-V3.2-Exp相似实现见 models/glm_5/models/modeling_glm.py把共享专家放到副流与 gating / dispatch / 路由专家路径重叠。最小形态是npu_stream_switch tagged event 组合——切流前npu_record_tagged_streamnpu_tagged_event_record副流内npu_tagged_event_wait后再算 shared experts最后npu_tagged_event_record供汇合点等待图模式下再叠加stream-fusion1编译选项。Indexer / Prolog 多流indexer-prolog-multi-stream.md源码见 models/glm_5/models/indexer.py把 Q 路径与权重投影路径拆到不同流indexer_stream/weights_stream用wait_event/wait_tensor表达依赖缩短 Indexer 前处理串行段——这类优化常常是前处理子链 overlap边界容易拆错。Prefill Micro-Batch 双流流水prefill-microbatch-dual-stream.md代表实现 DeepSeek-R1显式torch.npu.Stream()双流 record_event/wait_event把 dispatch、expert、combine 阶段流水化对应路由表中显式流对象 事件编排的用法。多流 控核联动longcat-flash-multi-stream-limit-core.md源码见 models/longcat_flash/models/modeling_longcat_flash.pyLongCat-Flash Stage2 中 Attention 路径与 shortcut MoE 路径双流并行再用limit_core_num(True, self.aic_num1, self.aiv_num1)给副流单独分核、主路径用另一套核数配置同时叠加npu_prefetch——这正是路由表overlap 成立但一条流明显拖尾 → 控核场景的完整实现且提示prefetch、superkernel、控核、多流四者是耦合设计拆开后收益可能不成立。选型时的通用建议先把当前优化归类到某一类模式MoE 双流 / Attention 前处理多流 / KVCache offload 异步流 / prefill 双流流水 / 多流 控核 / AFD 通信计算 overlap读对应案例确认模块边界、依赖关系和同步方式再读代表代码或补丁确认实际 API 风格与 enable 开关设计若一个实现同时落在多类模式里先选主模式再把它它能力当补充手段。最后任何副流已落到 side stream的结论都不能直接当方案成立——必须用 profiler 的Stream IDStart Time(us)Duration(us)计算overlap_pct判方案成立要 ≥ 0.5≤ 0.05即判假并行确认物理执行层面真的并行而不是逻辑分流但执行仍串行。【免费下载链接】cann-recipes-infer本项目针对LLM与多模态模型推理业务中的典型模型、加速算法提供基于CANN平台的优化样例项目地址: https://gitcode.com/cann/cann-recipes-infer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考