靜態圖(Static Graph)——深度學習編譯與執行的基石範式
3 秒看懂
靜態圖 = 先畫完整張計算藍圖,再喂資料跑。 把所有運算元、張量形狀、依賴關係一次性”凍結”成一張有向無環圖(DAG),編譯器拿到全圖後可以做極致最佳化(運算元融合、記憶體規劃、並行排程),但圖一旦固化就無法執行時動態改變結構。它是深度學習從”研究玩具”走向”工業部署”的關鍵範式躍遷。
3 分鐘產業解釋
為什麼一個”圖”的概念值得產業級關注?
深度學習架構本質上要回答一個問題:怎麼把使用者寫的 Python 數學表達變成能在 GPU/NPU 上高效跑的機器碼?
這裡存在兩種根本範式:
| 範式 | 通俗描述 | 代表 |
|---|---|---|
| 靜態圖(Define-then-Run) | 先把整個計算流程”編譯”成一張圖,然後反覆執行 | TF 1.x、ONNX、TensorRT、TVM |
| 動態圖(Define-by-Run) | 寫一行算一行,像 Python 原生執行 | PyTorch 預設模式、TF Eager |
靜態圖的核心價值在於:編譯器拿到全圖資訊後,能做跨運算元的全域性最佳化——這在工業部署中直接轉化為更低延遲、更高吞吐、更少視訊記憶體佔用。
產業位置: 今天的主流實踐是 “訓練用動態圖(靈活),部署轉靜態圖(高效)“。PyTorch 2.0 引入的 torch.compile 正是用 torch.fx 捕獲計算圖後編譯為靜態圖執行,代表了兩種範式的融合趨勢。
15 分鐘專家深入
1. 從”執行”到”編譯”:範式分野的本質
動態圖(Eager Mode):
# PyTorch 風格
a = x @ W1 + b1 # 立刻算
a = relu(a) # 立刻算
y = a @ W2 + b2 # 立刻算
- 優點: 和 Python 原生體驗一致,
print、if、for隨便用,除錯零門檻。 - 代價: 每一步都要回 Python 直譯器排程,無法做跨運算元最佳化;每次執行都要重新排程核心。
靜態圖(Graph Mode):
# TensorFlow 1.x 風格 —— 先定義圖,再啟動 Session 執行
a = tf.matmul(x, W1) + b1
a = tf.nn.relu(a)
y = tf.matmul(a, W2) + b2
# 此時沒有計算發生,只是在建置圖
with tf.Session() as sess:
result = sess.run(y, feed_dict={x: data}) # 真正執行
- 核心差異: 整個計算流程被序列化為一張 DAG,編譯器/執行時可以看到全貌。
2. 靜態圖的”全圖視野”帶來什麼最佳化?
這是靜態圖的真正產業價值所在,分三個層次:
層次一:運算元融合(Operator Fusion)
未融合:
MatMul → 寫回視訊記憶體 → BiasAdd → 寫回視訊記憶體 → ReLU → 寫回視訊記憶體
(3 次視訊記憶體讀寫, 3 次核心啟動開銷)
融合後:
FusedMatMulBiasReLU → 寫回視訊記憶體
(1 次視訊記憶體讀寫, 1 次核心啟動)
融合將多個小運算元合併為一個大運算元,減少視訊記憶體頻寬消耗和 GPU kernel launch 開銷。這在 Transformer 推論中尤為關鍵(如 QKV 投影的融合、Attention 中 softmax+scale 的融合)。
層次二:記憶體規劃(Memory Planning / Liveness Analysis)
編譯器對圖做張量生命週期分析——哪些中間結果在同一時刻存活、哪些已不再需要。據此做:
- 原位複用(In-place operation): 輸出複用輸入的緩衝區
- 記憶體重用(Memory reuse): 生命週期不重疊的張量共享同一記憶體塊
- 換入換出策略: 在視訊記憶體緊張時將非活躍張量解除安裝到主機記憶體
在大型模型訓練中(如數百層 Transformer),啟用值的記憶體規劃直接決定能否跑起來。
層次三:排程最佳化(Scheduling & Parallelism)
全圖可見後,編譯器可以:
- 識別無依賴的子圖並行執行(如多頭注意力的多個 head 平行計算、殘差分支的獨立前向與合併、無依賴運算元間的水平融合)
- 重疊計算與通訊(如 AllReduce 通訊與下一層計算 overlap)
- 跨裝置圖切分(Graph Partitioning):自動決定哪些運算元在哪個 GPU 上執行
3. 靜態圖的核心資料結構
┌─────────────────────────────────────────┐
│ Computation Graph (DAG) │
│ │
│ Node = Operator (運算元) │
│ - op_type: "Conv2D", "MatMul", ... │
│ - attrs: kernel_size, stride, ... │
│ - inputs: [TensorRef, ...] │
│ - outputs: [TensorRef, ...] │
│ │
│ Edge = Tensor 資料流 │
│ - dtype: fp16, bf16, fp32, ... │
│ - shape: [batch, seq, hidden] │
│ - device placement │
│ │
│ Metadata: │
│ - Control dependencies │
│ - Training ops (optimizer, gradient) │
│ - Placement constraints │
└─────────────────────────────────────────┘
圖的 IR(中間表示)是靜態圖系統的靈魂。不同架構/編譯器有自己的 IR:
- TensorFlow: GraphDef / SavedModel(Protocol Buffer 序列化)
- ONNX: 開放標準 IR,跨架構互操作的橋樑
- MLIR(Multi-Level IR): Google 主導的多層級編譯器基礎設施,支援從高層圖 IR 到低層硬體 IR 的逐層 lowering
- torch.fx: PyTorch 的圖捕獲 IR,用於
torch.compile的前端
4. 靜態圖的固有挑戰
| 挑戰 | 說明 |
|---|---|
| 動態形狀(Dynamic Shape) | 序列長度、batch 大小不固定時,靜態圖需要為每種 shape 編譯一個特化版本,或引入 shape 符號化抽象 |
| 控制流(Data-dependent branching) | if x > 0 這類資料依賴的分支在靜態圖中需要特殊運算元(如 tf.cond、tf.while_loop),表達力受限 |
| 除錯困難 | 圖編譯後的執行與使用者原始程式碼失去直接對應關係,報錯資訊晦澀 |
| 迭代開銷 | 研究階段頻繁修改模型結構時,每次都要重新”建圖→編譯”,開發體驗差 |
技術原理
靜態圖建置與執行的完整流程
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 使用者 Python │ │ 圖建置階段 │ │ 圖最佳化階段 │
│ API 呼叫 │────▶│ (Build) │────▶│ (Optimize) │
│ │ │ │ │ │
│ tf.matmul() │ │ 生成 DAG IR │ │ 運算元融合 │
│ tf.relu() │ │ 節點+邊+屬性 │ │ 常量摺疊 │
│ tf.Variable │ │ │ │ 死程式碼消除 │
│ │ │ │ │ 版面配置轉換 │
└──────────────┘ └──────────────┘ └──────────────┘
│
▼
┌──────────────┐ ┌──────────────┐
│ 執行階段 │ │ 程式碼生成/ │
│ (Run) │◀────│ 核心編譯 │
│ │ │ (CodeGen) │
│ Session.run()│ │ │
│ 或等價呼叫 │ │ 生成裝置程式碼 │
│ │ │ 或調優核心庫 │
└──────────────┘ └──────────────┘
靜態圖與動態圖的關鍵機制對比
靜態圖 動態圖
────── ──────
建置時機: 前向+反向全部建置完畢後才執行 每個 op 立即執行
圖結構: 一次建置,反覆執行(引數更新) 每次執行隱式重建圖
Python 互動: 建置期有,執行期無(圖已脫離Python) 每步都回 Python 排程
最佳化能力: 全圖最佳化(融合/排程/記憶體規劃) 僅單運算元級別最佳化
控制流: 需專用運算元(cond/while_loop) 原生 Python if/for
除錯: 困難(需專用工具如 TensorBoard) 簡單(標準 pdb/列印)
典型延遲: 核心啟動少,排程開銷低 每步有 Python 排程開銷
靜態圖中的控制流處理
這是理解靜態圖”表達力邊界”的關鍵:
# Python 原生控制流(動態圖天然支援)
if x.sum() > 0:
y = x * 2
else:
y = x * -1
# 靜態圖中的等價表達(TensorFlow 1.x 為例)
y = tf.cond(
tf.reduce_sum(x) > 0,
lambda: x * 2,
lambda: x * -1
)
# 兩條分支都會被編譯進圖,執行時根據條件選擇執行哪條
# 代價:兩條分支的記憶體都會被分配(或需要條件記憶體分配機制)
迴圈同理:
# 靜態圖中的迴圈(tf.while_loop)
result = tf.while_loop(
cond=lambda i, _: i < 10, # 迴圈條件
body=lambda i, acc: (i+1, acc+x), # 迴圈體
loop_vars=[0, tf.zeros_like(x)]
)
# 迴圈次數可以在執行時動態確定,不需要在圖建置時已知最大值;
# 但若迴圈體內張量形狀變化,需通過 shape_invariants 引數指定形狀約束以避免編譯衝突
圖最佳化 Pass 示例
編譯器對靜態圖施加的最佳化 Pass(以推論場景為例):
原始圖:
Input → Conv2D → BatchNorm → ReLU → Conv2D → BatchNorm → ReLU → Output
Pass 1 - BN 融入 Conv(Fold BatchNorm):
Input → [Conv2D+BN_fused] → ReLU → [Conv2D+BN_fused] → ReLU → Output
(將 BN 的 scale/bias 合併到 Conv 的權重中, 推論時消除 BN 計算)
Pass 2 - 運算元融合:
Input → [FusedConvBNReLU] → [FusedConvBNReLU] → Output
(Conv+BN+ReLU 合併為單個核心呼叫)
Pass 3 - 常量摺疊 + 精度轉換:
Input(fp16) → [FusedConvBNReLU(fp16)] → [FusedConvBNReLU(fp16)] → Output(fp16)
(將常量預計算, 並將精度降低以利用 Tensor Core)
這種多 Pass 流水線在 TensorRT、TVM、XLA 中是標準實踐。
技術演進史
| 時期 | 事件 | 意義 |
|---|---|---|
| ~2017 | Google 釋出 TensorFlow 1.0 | 靜態圖成為工業標準範式,“建圖→Session 執行”流程主導了早期 AI 工業化 |
| ~2017 | ONNX 格式由 Meta(時稱 Facebook)與 Microsoft 聯合發起 | 靜態圖的開放互操作標準,打通訓練→部署的跨架構流轉 |
| ~2016–2017 | PyTorch 開源,以動態圖(define-by-run)體驗迅速崛起 | 研究社群大量轉向動態圖,倒逼 TF 等架構改善易用性 |
| ~2017 | TVM(陳天奇等)釋出 | 將編譯器技術引入深度學習,通過靜態圖的自動調優實現跨硬體部署 |
| ~2019 | TensorFlow 2.0 引入 Eager Execution 為預設模式 | TF 內部也承認動態圖對研究的重要性,但保留 tf.function 實現圖編譯 |
| ~2019 | MLIR 由 Google Chris Lattner 提出並開源 | 多層級 IR 基礎設施,統一從高層圖到低層硬體的編譯鏈路 |
| ~2020 | JAX 崛起(Google),以 jit 裝飾器做 tracing-based 靜態圖編譯 | 證明”Pythonic 體驗 + 函式式語義 + 自動圖捕獲”的路線可行 |
| ~2023 | PyTorch 2.0 釋出 torch.compile,引入 torch.fx + dynamo + Inductor | 動態圖架構向靜態圖編譯融合的標誌性事件——“動態建置,靜態執行” |
| ~2023–至今 | AI 編譯器成為基礎設施競爭焦點(Triton、XLA、MLIR 生態擴張) | 靜態圖編譯不再是”TF vs PyTorch”的路線之爭,而是所有架構的公共底座 |
核心趨勢: 靜態圖沒有”消亡”,而是從使用者介面層退隱到編譯器底層。使用者寫動態圖程式碼,架構在背後捕獲並編譯為靜態圖執行。兩種範式走向融合。
技術路線對比
| 維度 | 純靜態圖(TF 1.x 風格) | 純動態圖(PyTorch Eager) | 混合模式(torch.compile / JAX jit) |
|---|---|---|---|
| 使用者體驗 | 差(反直覺的建圖模式) | 優(等同 Python) | 良(Pythonic + 首次編譯等待) |
| 除錯難度 | 高 | 低 | 中(需理解 graph break 等概念) |
| 全圖最佳化能力 | 強 | 無 | 強(編譯階段) |
| 動態形狀支援 | 差(需 shape 符號化) | 天然支援 | 中(正在快速改善) |
| 控制流表達 | 受限(專用運算元) | 原生 Python | 部分受限(需 traceable) |
| 推論部署效能 | 優秀 | 一般 | 優秀 |
| 跨裝置圖切分 | 成熟 | 手動 | 發展中 |
| 當前產業地位 | 遺留/部署主導 | 研究/訓練主流 | 新範式方向 |
關鍵結論: 純靜態圖作為使用者介面已被動態圖取代,但作為編譯目標仍是所有高效能執行的基石。
上下游
上游:誰提供/需要靜態圖?
使用者程式碼(Python)
│
▼
深度學習架構(PyTorch / TensorFlow / JAX / PaddlePaddle)
│
├── 圖捕獲(Graph Capture / Tracing)
│ • torch.fx / torch.dynamo
│ • tf.function / AutoGraph
│ • JAX jit (jaxpr)
│
▼
靜態計算圖 IR
│
├── 標準化格式:ONNX
└── 架構內部 IR:GraphDef / MLIR dialect
下游:靜態圖流向哪裡?
靜態圖 IR
│
├──▶ 編譯器後端(最佳化 + 程式碼生成)
│ ├── XLA(Google,服務 TPU/GPU)
│ ├── TensorRT(NVIDIA,GPU 推論加速)
│ ├── TVM / Apache TVM(跨硬體)
│ ├── Triton(OpenAI,GPU kernel 編寫)
│ └── 各廠商自研編譯器(昇騰 MindSpore 圖編譯等)
│
├──▶ 模型序列化與交換
│ └── ONNX → 各推論引擎(ONNX Runtime、TensorRT 等)
│
└──▶ 分散式執行引擎
└── 圖切分 → 跨裝置排程(多 GPU/多節點)
關鍵中介軟體:ONNX 的角色
ONNX(Open Neural Network Exchange)是靜態圖領域的”通用語言”:
- 定義了一套標準運算元集(運算元版本持續演進)
- 模型以 Protocol Buffer 格式序列化(
.onnx檔案) - 訓練架構匯出 → ONNX → 推論引擎匯入,是目前最廣泛的跨架構部署路徑
關鍵指標
評估靜態圖質量(或編譯器效果)的核心指標:
| 指標 | 說明 |
|---|---|
| 首編譯時間(Time-to-First-Inference) | 從圖建置到首次可執行的耗時,靜態圖系統通常較長 |
| 推論延遲(Latency) | 單次前向傳播耗時,靜態圖最佳化後的核心優勢 |
| 吞吐量(Throughput) | 單位時間處理樣本數,batch 越大靜態圖優勢越明顯 |
| 視訊記憶體峰值(Peak Memory) | 圖最佳化(記憶體重用/原位操作)可顯著降低 |
| 運算元融合率 | 融合運算元數 / 總運算元數,衡量編譯器最佳化深度 |
| 圖捕獲覆蓋率 | 能被成功編譯的程式碼佔比(混合模式下,未覆蓋部分退回 eager) |
| 跨 shape 泛化能力 | 同一編譯結果能覆蓋多少種輸入形狀(動態 shape 支援) |
供需與市場資料
為什麼靜態圖(編譯最佳化)成為產業熱點?
-
模型越來越大,部署成本飆升: 大語言模型推論成本是訓練成本的持續消耗項。靜態圖編譯最佳化(運算元融合、量化、記憶體最佳化)是不改變模型就能降低推論成本的最直接手段。
-
硬體碎片化: NVIDIA GPU、AMD GPU、Google TPU、國產 NPU、行動端 NPU……硬體越來越多。靜態圖作為編譯器的輸入,是實現**“一次建圖,多硬體部署”**的關鍵抽象層。
-
編譯器人才稀缺: 能做 AI 編譯器(融合編譯器技術 + 深度學習 domain knowledge)的團隊全球極少。掌握 MLIR、TVM、XLA 等技術的工程師成為各廠爭奪的稀缺資源。
市場規模參考
靜態圖編譯最佳化不是獨立產品類別,而是嵌入在以下市場中:
- AI 編譯器/推論最佳化工具鏈:嵌入在推論架構(TensorRT、ONNX Runtime、各廠自研引擎)中,整體推論最佳化市場隨 AI 部署規模同步擴張。
- AI 基礎設施軟體:各雲端廠商/AI 公司均在自研或定製編譯器棧,作為差異化競爭力的核心組成部分。
[未充分揭露] 獨立的”靜態圖編譯”市場規模資料,因其作為技術元件嵌入更大系統中。可參考推論伺服器/架構相關市場規模作為間接指標。
代表公司與資本對映
| 公司/組織 | 靜態圖相關版面配置 | 角色 |
|---|---|---|
| XLA(TPU/GPU 編譯器)、MLIR(開源 IR 基礎設施)、JAX(jit 編譯)、TF SavedModel | 編譯器基礎設施主導者 | |
| NVIDIA | TensorRT(推論編譯最佳化)、TensorRT-LLM、cuDNN 圖級 API | GPU 推論最佳化的事實標準 |
| Meta / PyTorch | torch.compile(dynamo + Inductor)、torch.fx、ExecuTorch | 動態圖→靜態圖融合的推動者 |
| Apache TVM 專案 | TVM / Unity(自動調優編譯器,跨硬體) | 開源跨平台編譯器代表 |
| OpenAI | Triton(GPU kernel DSL,被 Inductor 後端採用) | Kernel 程式設計新範式 |
| Microsoft | ONNX Runtime(跨平台推論引擎)、ONNX 標準聯合主導 | 推論部署中介軟體 |
| 華為 | MindSpore 圖編譯(CANN 運算元編譯)、昇騰推論引擎 | 國產 AI 編譯器自主路線 |
| 百度 | PaddlePaddle 靜態圖(早期定位 + PHI 運算元庫) | 國產架構代表 |
| Intel | OpenVINO(模型最佳化與推論部署)、oneDNN | 邊緣推論最佳化 |
| Apple | Core ML(模型編譯與部署)、MLX(動態+編譯混合) | 端側部署編譯 |
投資邏輯
核心觀點
靜態圖不是”一個產品”,而是 AI 基礎設施中不可替代的編譯最佳化層。
投資對映思路
-
“賣鏟子”邏輯 —— 編譯器/推論引擎廠商:
- NVIDIA(TensorRT 是其推論護城河的核心元件)
- 具備自研 AI 編譯器能力的雲端廠商(Google、華為、百度等)在推論成本上有結構性優勢
-
“路基”邏輯 —— 編譯器基礎設施:
- MLIR 已成為事實上的編譯器 IR 標準,圍繞 MLIR 的工具鏈和人才是稀缺資源
- Triton 等 kernel DSL 正在重塑 GPU 程式設計範式
-
“瓶頸”邏輯 —— 硬體碎片化催生編譯器需求:
- 每出一款新 AI 晶片,都需要編譯器適配。編譯器能力直接決定硬體的實際可用效能
- 國產 AI 晶片的競爭,很大程度上是編譯器生態的競爭
風險提示
- 編譯器技術壁壘高但商業模式不易獨立成立(通常嵌入更大產品中)
- 架構高度碎片化導致編譯器生態分裂,標準統一程序不確定
- 硬體迭代速度快,編譯器需持續跟進,研發投入大
常見誤讀糾偏
誤讀 1:“靜態圖已經被淘汰了,現在都用動態圖”
糾偏: 靜態圖作為使用者介面確實已非主流,但作為編譯器目標從未離場——恰恰相反,它的重要性在增加。torch.compile 的本質就是把動態圖程式碼捕獲為靜態圖再編譯執行。JAX 的 jit 同理。**“動態圖做介面,靜態圖做執行”**是當前範式,不是靜態圖消亡。
誤讀 2:“靜態圖不能處理動態形狀”
糾偏: 靜態圖處理動態形狀確實更復雜,但並非不可能。解決方案包括:
- 形狀符號化(Symbolic Shapes): 用符號變量表示未知維度,編譯時生成含符號的通用核心,執行時特化
- 多版本編譯: 為常見的幾種 shape 各編譯一個版本,執行時根據實際 shape 選擇
- Dynamic Batching: 推論引擎層面將不同長度的請求 padding 到統一 shape
XLA 和 TensorRT 近年都在大幅改善動態 shape 支援。準確說法是”靜態圖處理動態 shape 的開銷更高、更復雜”,而非”不能”。
誤讀 3:“TensorFlow = 靜態圖,PyTorch = 動態圖”
糾偏: 這是 2017–2019 年的刻板印象。TF 2.x 預設 Eager + tf.function 圖編譯;PyTorch 2.0 的 torch.compile 本質也是圖編譯。兩種架構都在融合兩種範式,區別更多在於編譯器實現路徑和社群生態,而非”靜態 vs 動態”的二元對立。
誤讀 4:“靜態圖一定比動態圖快”
糾偏: 靜態圖提供了最佳化的可能性,但不自動等於更快。一張沒有經過任何最佳化 Pass 的靜態圖,執行效率可能和動態圖相當甚至更低(序列化/反序列化開銷)。真正的效能優勢來自於編譯器最佳化(融合、排程、記憶體規劃)。另外,如果模型很小(如簡單 MLP),動態圖的排程開銷可以忽略,靜態圖的優勢不顯著。靜態圖的效能優勢隨模型複雜度和 batch size 增大而增大。
學習路徑
入門(理解概念)
- PyTorch 官方文件
torch.compile教程 —— 從動態圖到編譯的體驗 - TensorFlow
tf.function指南 —— 理解 AutoGraph 如何將 Python 轉為圖 - 動手:用 Netron 工具視覺化一個 ONNX 模型,觀察靜態圖的節點與邊
進階(理解最佳化)
- 學習 TVM 教程(TVM 文件中的 “Tensor Operations” 和 “Optimizing Operators” 章節)
- 閱讀 XLA 概述文件 —— 瞭解 Google 的圖編譯最佳化 Pass
- 研究 TensorRT 的最佳化流程(層融合、精度校準、Kernel Auto-tuning)
深入(理解編譯器)
- 研讀 MLIR 概念論文 “MLIR: A Compiler Infrastructure for the End of Moore’s Law”(Chris Lattner et al.)
- 閱讀 PyTorch 2.0 架構部落格(dynamo → AOTAutograd → Inductor 的 pipeline)
- 研究陳天奇 TVM 論文 “TVM: An Automated End-to-End Optimizing Compiler for Deep Learning”
實踐
- 將一個 PyTorch 模型匯出為 ONNX,用 ONNX Runtime 對比最佳化前後的推論延遲
- 用
torch.compile編譯一個 Transformer 模型,觀察 compilation time vs inference speedup 的權衡 - 嘗試在 Triton 中編寫一個自定義融合運算元,理解 kernel 編譯層面的最佳化
一句話總結
靜態圖是深度學習從”能跑”到”跑得快”的技術基石——使用者介面層面它已讓位於動態圖的靈活性,但在編譯器底層,它作為全域性最佳化的唯一載體,正成為 AI 基礎設施中最關鍵的隱性競爭力。
延伸閱讀與來源
| 資源 | 型別 | 說明 |
|---|---|---|
| TVM 論文:TVM: An Automated End-to-End Optimizing Compiler for Deep Learning | 學術論文 | AI 編譯器領域的奠基性工作 |
| MLIR 論文:MLIR: Scaling Compiler Infrastructure for Domain Specific Computation | 學術論文 | 現代 AI 編譯器 IR 基礎設施 |
| PyTorch 2.0 官方部落格 / Architecture Overview | 官方文件 | 理解 dynamo + Inductor 架構 |
| TensorFlow Graph 指南 | 官方文件 | 經典靜態圖系統的設計思路 |
| NVIDIA TensorRT Developer Guide | 官方文件 | 推論編譯最佳化的工業實踐 |
| ONNX 官方文件(onnx.ai) | 標準文件 | 靜態圖互操作標準 |
| Deep Learning Compilation (陳天奇 talks / TVM tutorials) | 教程/演講 | 編譯器技術的直覺建立 |
| Triton 文件(triton-lang.org) | 官方文件 | GPU kernel 程式設計新範式 |
注:本文技術描述基於深度學習編譯領域的公開論文、架構文件與社群共識。具體架構版本的效能資料因硬體、模型、配置差異較大,建議以實際 benchmark 為準。市場資料方面,AI 編譯器尚無獨立市場研究,相關判斷基於產業觀察定性分析。