ATSInfer: 張量級 Hybrid CPU-GPU 排程 — 讓消費級裝置跑 LLM 快 3.3 倍
一句話核心結論
現有 hybrid CPU-GPU 推論系統用 layer 級或 expert 級 的粗粒度 offloading,忽略同一層內不同 tensor 的運算強度差異巨大,且排程策略不隨裝置當下的 CPU/GPU/PCIe 負載動態調整。ATSInfer 首創 tensor 粒度 offloading,結合 靜態張量放置(knapsack DP)+負載感知動態傳輸(online DP)+非同步 CPU-GPU 協調,在消費級 GPU(RTX 3060/4060/4090)上 decode 吞吐量最高 +229%(3.29x)、prefill 吞吐量最高 +94%(1.94x)、GPU 利用率提升約 70%。實作僅約 15,000 行 C++,擴充 llama.cpp,同時支援 dense 與 MoE 模型。
Decode 吞吐量
最高 3.29x vs llama.cpp
Prefill 吞吐量
最高 1.94x vs llama.cpp
GPU 利用率
decode 期間平均 +70%
核心洞察:粗粒度 offloading 的兩個致命缺陷
ATSInfer 從實證出發,揭示了現有系統的兩個系統性瓶頸:
- Intra-layer 張量異質性被忽略:同一層 Transformer 內的 Q/K/V/O projection、FFN up/gate/down、attention output 等張量的運算強度和 GPU 加速比差異懸殊。圖 3 顯示同一層內某些 tensor 搬上 GPU 的 latency reduction 是其他的 數倍。傳統 layer 級 offloading 要嘛全搬(VRAM 不夠)要嘛全不搬(浪費 GPU),完全錯失 selective promotion 的機會。
- 消費級裝置的負載是動態的:筆電/桌機同時跑瀏覽器、IDE、媒體播放,CPU/GPU 資源持續變動。更關鍵的是 thermal throttling——長時間高負載後處理器降頻,CPU 執行時間飆升。圖 4 展示了背景干擾→熱牆觸發的兩階段效能衰減,固定排程策略對此完全無能為力。
這兩個缺陷的疊加效果:粗粒度 + 靜態策略 = CPU 長期成為瓶頸、GPU 大量閒置、PCIe 頻寬未被充分利用。
技術架構:三層協同設計
ATSInfer 在 llama.cpp 上新增約 15,000 行 C++,分三層:
- ① 非同步 CPU-GPU 協調層:精心設計三區記憶體佈局——GPU resident region(靜態放置的常駐張量)、CPU pinned-memory storage(無法常駐 GPU 的張量,用 mapped + pinned 加速傳輸)、GPU temporary buffers(按 tensor 生命週期復用的暫存區)。在此之上建立雙 stream 管線:compute stream(序列化運算+activation 傳輸,跑在 GPU SM 上)+transfer stream(非同步權重搬移,跑在 Copy Engine 上)。關鍵設計是 activation 傳輸用 Zero-Copy kernel(SM 驅動)而權重傳輸用 Copy Engine——避免小 activation 被大 weight 傳輸阻塞。
- ② 靜態張量放置(Knapsack DP):定義 empirical performance density k_i = t_i / s_i(單位記憶體的執行成本)。對每個 tensor 在 CPU 和 GPU 上分別量測實際執行時間,計算 GPU 加速效益 r_i = t_i^c - t_i^g。將放置問題建模為 knapsack-style 優化:max Σ(r_i · GPU 標記) − Σ(c_i · backend switch penalty),subject to GPU memory budget。用 dynamic programming 求解,複雜度 O(nM),MB 粒度量化後可在數秒內完成。
- ③ 負載感知動態傳輸(Online DP):每輪 prefill/decode 前,從 runtime measurements 刷新 CPU 速度、GPU 速度、傳輸頻寬、重疊機會的估計值。對 CPU-resident tensor 評估「臨時提升到 GPU 執行」的淨效益——只有當 weight 傳輸能被前面的計算完全遮蓋(或遮蓋到讓淨效益為正)時才觸發。同樣用 DP 求解最優排程,但每次 rerun 以反映最新負載狀態。MoE decode 時只傳 activated experts 的權重,大幅縮小傳輸量。
這三層的協同效應:靜態放置確保高價值 tensor 始終在 GPU → 動態傳輸在 CPU 瓶頸時把額外工作卸到 GPU → 非同步管線讓傳輸與計算最大化重疊。
實驗結果:三個消費級 GPU 跨模型驗證
ATSInfer 在 RTX 3060(6GB)、RTX 4060(8GB)、RTX 4090(24GB)上測試 dense(Qwen3-14B、Llama-4-Scout-17B)和 MoE(Qwen3-30B-A3B、DeepSeek-V3-Lite)模型:
- Decode 吞吐:RTX 3060 上 Qwen3-14B 達 3.29x(最大增益來自小 VRAM 場景——GPU 記憶體越緊,精細放置的價值越大);RTX 4090 上仍有 1.4-1.8x。
- Prefill 吞吐:最高 1.94x(prefill 是 compute-bound,GPU 本身已很快,增益主要來自減少 CPU 端的序列化瓶頸)。
- GPU 利用率:decode 期間從 llama.cpp 的 ~18% 提升到 ~31%(RTX 3060),相對提升約 70%。
- PCIe 頻寬使用:更有效地利用可用頻寬,避免 llama.cpp 常見的「GPU 閒置等權重」或「PCIe 閒置等 GPU」的蹺蹺板效應。
- 消融實驗:單獨移除動態傳輸(只用靜態放置)→ decode 吞吐下降 15-25%;單獨移除非同步管線(同步傳輸)→ 下降 20-30%。兩者疊加效果大於各自獨立效果之和。
對 DKY / Hermes 的啟發
ATSInfer 雖是系統 infra 論文,但三個設計決策對 DKY 的推論部署有直接參考價值:
- 實證驅動的資源配置:ATSInfer 不依賴理論 FLOP 分析,而是直接量測每個 tensor 在目標硬體上的實際執行時間(empirical performance density)。這個方法論可以直接套用到 DKY 環境——在 ARM 伺服器上部署模型前,先 profile 各運算元的實際延遲而非看 spec sheet。
- 消費級 GPU 仍大有可為:RTX 3060(6GB VRAM)透過 tensor 級排程能跑到 3.29x decode 吞吐量,說明瓶頸不在硬體而在排程。DKY 若有本地推論需求(隱私敏感場景),不必追最新硬體。
- llama.cpp 生態的擴充性:ATSInfer 僅 15,000 行 C++ 就實現了顯著提升,且作為 llama.cpp 的擴充(非 fork),可隨上游更新。這對 Hermes 的工具選擇策略有啟發:優先選生態活躍的基底(llama.cpp),在其上做針對性優化。
限制
- 目前僅支援 NVIDIA GPU(CUDA),不支援 Apple Silicon(MPS)或 AMD(ROCm),雖然架構設計是後端無關的
- 靜態放置的 profiling 階段需要幾分鐘,換模型或換硬體時須重新執行
- 動態傳輸的 online DP 雖為 O(n²),但在超大模型(>100B)上可能成為 per-step 延遲瓶頸
- 未考慮多 request 並行場景——消費級裝置的 batch size 通常為 1,但若未來 local agent 需要並行工具呼叫則需擴充
- 量化模型的 tensor 粒度行為可能與 FP16 不同,論文未單獨評估 INT4/INT8 場景