ge(Graph Executor):昇腾 CANN 的“大脑“,图编译和执行到底是怎么工作的
在昇腾 CANN 里,有一个仓库叫 ge,全称 Graph Executor,翻译过来就是图执行引擎。
这个名字听起来很底层,很多人不知道它是干什么的。但如果你在昇腾 NPU 上跑过模型,不管是训练还是推理,你的模型都要经过 ge 的处理——它是昇腾 CANN 里负责图编译、图优化、图执行的核心组件。
今天把 ge 说清楚。
ge 到底是什么
ge 是昇腾 CANN 开源社区里的一个核心仓库,定位是图执行引擎。它负责把上层框架(PyTorch、TensorFlow、MindSpore 等)传下来的计算图,编译成昇腾 NPU 能高效执行的格式。
这里有个关键概念要讲清楚:计算图。
你写的 PyTorch 模型,本质上是一个计算图——每一层是一个节点,层之间的数据流是边。PyTorch 默认是 eager 模式(动态图),每执行一行代码就马上算;但要想在 NPU 上跑得快,必须把整个计算图 capture 下来,做全局优化,再编译成 NPU 的机器码。
ge 就是做这件事的:捕获计算图 → 图优化 → 编译成 NPU 可执行格式。
昇腾异构计算架构里,ge 的位置在这里:
框架层(PyTorch / TensorFlow / MindSpore / ...)
└─ 框架适配器(Framework Adaptor,CANN 第2层)
└─ ge(图执行引擎,编译 + 执行)
└─ BiSheng / ATC 编译器(CANN 第3层,生成 NPU 机器码)
└─ 昇腾 NPU 硬件
ge 的核心工作流程
ge 的工作可以分成三个阶段:图准备、图编译、图执行。
第一阶段:图准备。 ge 从框架适配器拿到计算图(可能是 ONNX 格式,也可能是框架自己的图格式),然后做初步的图解析——把图里的算子节点和边整理成 ge 自己的图表示(叫 GE Graph)。
这个阶段还会做算子合法性检查——看看图里有没有 ge 不支持的算子,如果有,提前报错,避免编译到一半失败。
第二阶段:图编译。 这是 ge 最核心的阶段,做了大量优化:
GE Graph
├─ 算子融合(Operator Fusion):把相邻的小算子合并成大算子
├─ 内存优化(Memory Optimization):复用显存,减少显存峰值占用
├─ 数据流转优化(Data Flow Optimization):减少 DDR 和 SRAM 之间的数据搬运
└─ 生成编译中间表示(IR)→ 交给 BiSheng / ATC 编译器 → NPU 机器码
第三阶段:图执行。 编译完成后,ge 把 NPU 机器码加载到 NPU 上执行。这个阶段 ge 还负责运行时管理——显存分配、算子执行顺序调度、异常处理等。
# ge 的工作对大多数开发者是透明的
# 你只需要正常写 PyTorch 代码,ge 会在底层自动处理
import torch
import torch_npu
# 把模型转成 NPU 可调用的格式(底层调用 ge)
model = YourModel().npu()
# 推理模式,ge 会捕获计算图并编译
with torch.no_grad():
output = model(input_npu) # 第一次跑:ge 捕获图 → 编译 → 执行
# 后续跑:直接执行编译好的图,很快
ge 和图自动融合(graph-autofusion)的关系
又是一个容易混淆的点。ge 里也做算子融合,graph-autofusion 仓库也做算子融合,它们有什么区别?
简单说:ge 做的是离线融合(编译期),graph-autofusion 做的是在线融合(运行期)。
| 维度 | ge(图执行引擎) | graph-autofusion |
|---|---|---|
| 融合时机 | 编译期(离线) | 运行期(在线) |
| 融合策略 | 基于静态图结构,全局优化 | 基于实际运行时数据 shape,动态决策 |
| 适用场景 | 固定 shape 的推理(部署场景) | 变长序列推理(LLM 场景) |
| 性能稳定性 | 高(编译期已定) | 中(运行时决策,偶尔选错) |
如果你在做什么推理部署,模型 shape 是固定的,ge 的离线融合效果更稳定,性能也更好。
如果你在做什么大模型推理,输入序列长度是变的(512、1024、2048 都可能出现),graph-autofusion 的在线融合更灵活,能根据实际 shape 选择最优融合策略。
ge 和 TorchAir 的关系
TorchAir 是昇腾提供的一个工具,专门用来把 PyTorch 的动态图转换成 GE 的静态图。
PyTorch 默认是动态图(eager mode),每执行一行代码就马上算;但 ge 需要静态图(整个计算图都确定了才能编译优化)。这两个之间的矛盾,TorchAir 来解决。
工作流程:
PyTorch 动态图
└─ TorchAir(捕获动态图,转换成静态图表示)
└─ ge(编译静态图,生成 NPU 可执行格式)
└─ 执行
如果你在用 PyTorch 做昇腾 NPU 的推理部署,大概率会和 TorchAir 打交道。训练场景一般用动态图(eager mode)就行,不需要 TorchAir;但推理部署场景,用 TorchAir + ge 的静态图编译,性能会好很多。
ge 的几个关键概念
理解 ge,需要理解几个它里面的核心概念:
GE Graph:ge 内部的计算图表示。所有的图优化、图编译,都是基于 GE Graph 做的。
GE Operator:GE Graph 里的节点,对应一个算子(比如 MatMul、ReLU 等)。每个 GE Operator 有自己的输入输出描述、属性配置等。
GE Session:ge 的执行会话。一个 GE Session 管理一个计算图的完整生命周期——编译、执行、销毁。
GE Graph 优化 pass:ge 内置了很多图优化 pass(类似编译器里的优化 pass),比如:
- 算子融合 pass:合并相邻算子
- 内存复用 pass:让不同算子复用同一块显存
- 死代码消除 pass:删掉计算图里没有用到的节点
这些 pass 在图编译阶段自动执行,不需要开发者手动配置。
几个踩坑经验
坑一:第一次跑模型会很慢。 ge 的图编译是需要时间的,特别是大模型,第一次跑的时候要等它编译完。编译完成后,后续的推理会很快(因为直接用编译好的图)。如果你在做什么在线服务,建议先做预热(warm-up)——用几个 dummy 输入跑一遍模型,触发 ge 的图编译,避免第一个真实请求卡很久。
坑二:动态 shape 场景要小心。 ge 擅长静态 shape(编译期 shape 就确定了),如果你在做什么输入 shape 会变的应用(比如 LLM 推理),ge 可能每次都要重新编译图,性能很差。这种场景建议用 graph-autofusion 的在线融合,或者给 ge 配置 shape 范围(告诉 ge 可能的 shape 范围,让它提前编译多个版本的图)。
坑三:ge 的报错信息不太友好。 如果图编译失败,ge 报的错误有时候比较底层,不好定位问题。建议先在自己的开发机上用 CPU 模式把模型调通,再拿到 NPU 上跑——这样至少能排除模型代码本身的 bug,确定是 ge 编译的问题。
结尾
ge 是昇腾 CANN 生态里最底层的图执行引擎,它不性感,但每个跑在昇腾 NPU 上的模型都要经过它。
理解 ge 的价值不在于"怎么直接用它"(大多数时候框架适配器帮你调了),而在于理解你的模型在 NPU 上是怎么被编译、怎么被优化的、什么场景 ge 效果好、什么场景要用别的方案。
和 graph-autofusion(在线融合)、TorchAir(PyTorch 图转换)一起,构成了昇腾 NPU 完整的图编译和执行体系。
源码在 https://atomgit.com/cann/ge
更多推荐




所有评论(0)