llama.cpp 多 GPU 性能實測思路:2x V100 16GB 會比單卡 32GB 快嗎?

整理 llama.cpp 多 GPU offload 的性能預期:單卡能放下時雙卡不一定更快,單卡放不下時雙卡主要價值是把模型留在 GPU 上,並說明 V100 PCIe 與 NVLink 對性能的影響。

大概結論:llama.cpp 多 GPU offload 不是「多一張卡就白撿一倍性能」。如果模型本來能完整放進一張 32GB 顯卡,2x V100 16GB 通常不如單張 32GB 顯卡省心,甚至可能更慢;如果模型單張 16GB 放不下,雙卡的主要價值是「能把模型放進 GPU」,這時收益會很明顯。

先分清 split mode

llama.cpp 的多 GPU 主要圍繞 --split-mode--tensor-split 使用。實際討論性能時,先要區分幾種模式:

  • layer:按層切分到不同 GPU,兼容性較好,也是多數人優先嘗試的方式。
  • tensor:把張量計算拆到多張 GPU 上,更接近並行計算,但更依賴 GPU 之間的互聯頻寬和後端支援。
  • row:舊的行切分方式,在不少場景裡仍能看到,但新部署通常不建議優先從它開始。

簡單說,layer 更像「把不同樓層放在不同卡上」,單 token 生成時不一定能讓兩張卡同時滿負載;tensor 更像「同一層兩張卡一起算」,理論上更能並行,但跨卡通訊會成為關鍵瓶頸。

單卡 32GB 能放下時:雙 16GB 不一定更快

如果模型和 KV cache 能完整放進一張 32GB 顯卡,那麼單卡通常更穩,也常常更快。對 1x V100 32GB 和 2x V100 16GB 這類同代硬體來說,後者未必能贏。

比較保守的預期是:2x V100 16GB 可能比單張 V100 32GB 慢 10% 到 40%,尤其是單人聊天、Continue Agent、程式碼問答這類一次主要生成一個回答的場景。

原因不複雜:多 GPU 不是簡單合併顯存。按層切分時,推理會在不同 GPU 之間流轉,單 token 生成階段經常是部分 GPU 等另一部分 GPU;按張量切分時,兩張卡可以一起算,但中間結果需要跨卡同步,互聯頻寬和延遲會直接影響吞吐。

所以如果你的選擇是:

  • 1x V100 32GB
  • 2x V100 16GB

並且目標模型單張 32GB 已經能完整放下,那麼單張 32GB 往往是更舒服的選擇。

單卡 16GB 放不下時:雙卡價值很大

另一種情況完全不同:模型單張 16GB 放不下,但兩張 16GB 合起來可以放下。

這時雙卡的價值就很直接:

  • 單張 16GB:可能需要大量 CPU offload,速度明顯變慢。
  • 2x 16GB:權重盡量留在 GPU 上,速度可能比 CPU/GPU 混跑快很多。

這種場景下,2x V100 16GB 不一定比單張 32GB 快,但它可能比「單張 16GB 加大量系統記憶體 offload」快幾倍。也就是說,雙卡的第一價值不是加速,而是避免模型被迫落到更慢的系統記憶體裡。

V100 PCIe 和 V100 SXM2 差別很大

多 GPU 推理最容易被忽略的是互聯。

如果是 V100 SXM2,並且機器裡有 NVLink,跨卡通訊頻寬高很多。NVIDIA 的 V100 資料裡,NVLink 互聯最高可到 300GB/s。這種環境下,tensor 或更高 batch 的場景才更有機會接近甚至超過單卡表現。

如果是 V100 PCIe,情況就保守得多。V100 PCIe 的互聯主要走 PCIe Gen3,資料裡標的 interconnect bandwidth 是 32GB/s。這個頻寬和 NVLink 不是一個量級,所以雙卡經常出現「顯存夠了,但速度沒有翻倍」的情況。

因此判斷 2x V100 16GB 值不值得,不能只看顯存相加是 32GB,還要看它們是 PCIe 版還是 SXM2/NVLink 版。

怎麼選更實際

如果模型能放進單張 32GB 顯卡,優先選單卡。它的延遲、穩定性和調參成本通常更好。

如果模型單張 16GB 放不下,而兩張 16GB 能放下,雙卡值得用。此時重點是讓權重盡量留在 GPU,而不是期待性能線性翻倍。

如果是 V100 PCIe 雙卡,優先嘗試 --split-mode layer,把目標放在「能穩定跑」和「少走 CPU」上。

如果是 V100 SXM2/NVLink,才更值得測試 tensor 相關模式,尤其是 prefill、大 batch 或併發請求場景。

什麼時候買 2x16GB,什麼時候買 1x32GB

如果你只服務一個人,主要做聊天、程式碼補全、Continue Agent、長上下文問答,並且目標模型能放進 32GB,那麼 1x32GB 通常更值得。它少了跨卡調度,延遲更穩定,排查問題也簡單。

如果你已經有一張 16GB 卡,想用較低成本擴到能跑 30B、32B 或更高量化模型,2x16GB 就有意義。它不一定讓 token/s 翻倍,但可以把原本必須 CPU offload 的權重留在 GPU 上。

如果你準備重新採購,優先級可以這樣排:

  • 單模型、單使用者、重視回應延遲:優先 1x32GB。
  • 模型單卡放不下、預算有限:可以考慮 2x16GB。
  • 有 NVLink 或 SXM2 機器:2x16GB 的可玩性明顯高於普通 PCIe 雙卡。
  • 未來想跑更長上下文:不要只看權重大小,還要預留 KV cache 顯存。

layer split 和 tensor split 怎麼用

實用建議是:先用 layer,再測 tensor

layer 適合作為預設起點。它按層分配模型,兼容性較好,對 PCIe 雙卡更友好。缺點是生成階段可能更像流水線,某些時刻只有一張卡在忙,另一張卡在等。

tensor 更適合互聯頻寬好的機器,例如 V100 SXM2/NVLink。它把同一層的部分計算拆到多張卡上,理論上更有並行空間,但跨卡同步更頻繁。如果是 PCIe 雙卡,tensor 可能會被通訊開銷吃掉收益。

實際測試時可以從這幾組開始:

1
2
3
llama-bench -m model.gguf -ngl 99 --split-mode layer --tensor-split 1,1
llama-bench -m model.gguf -ngl 99 --split-mode tensor --tensor-split 1,1
llama-bench -m model.gguf -ngl 99 --split-mode layer --tensor-split 1,0

第三條不是為了長期使用,而是給單卡結果做一個參照。這樣才能看出雙卡到底是更快,還是只是把顯存壓力分攤出去了。

prefill 和 decode 為什麼表現不同

本地大模型性能通常要分成兩個階段看:

  • prefill:處理輸入 prompt,典型指標是 pp512 這類 prompt processing 吞吐。
  • decode:逐 token 生成回答,典型指標是 tg128 這類 token generation 吞吐。

prefill 更像大批量矩陣計算,batch 較大時更容易把 GPU 餵飽,也更可能從多 GPU 並行裡受益。decode 是一個 token 接一個 token 生成,batch 小、同步頻繁,跨卡通訊和調度延遲更容易暴露出來。

所以你可能會看到一種結果:雙卡的 pp512 更好,但 tg128 沒明顯提升,甚至更慢。對聊天和 Agent 來說,使用者體感更接近 tg128;對長文件導入、批量預填充、併發服務來說,pp512 也很重要。

KV cache 會不會成為第二個顯存瓶頸

會。很多人只算模型權重,忘了 KV cache。

模型權重決定「能不能載入模型」,KV cache 決定「能不能開足上下文」。上下文越長、併發越高、batch 越大,KV cache 佔用越明顯。你可能遇到這種情況:模型本體能放進 32GB,但一開 32K 或 64K 上下文,顯存又不夠了。

判斷時至少要留出幾塊顯存餘量:

  • KV cache
  • CUDA graph 或後端執行時開銷
  • prompt batch 和 ubatch
  • 系統桌面、驅動和其它程序佔用

如果你用的是 2x16GB,顯存不是一個完全等價的 32GB 大池子。某些緩衝區、KV cache 或中間張量仍然會受單卡剩餘顯存影響。測試長上下文時,最好直接用目標 --ctx-size 和目標併發數測,而不是只看模型能不能啟動。

用 llama-bench 做自己的雙卡測試

llama-bench 比直接聊天更適合做硬體對比,因為它會把 prompt processing 和 token generation 拆成可比較的指標。官方 README 的預設示例就是:

1
llama-bench -m model.gguf

對雙 V100,可以至少測這幾組:

1
2
3
4
5
6
7
8
# 單卡基線
CUDA_VISIBLE_DEVICES=0 llama-bench -m model.gguf -ngl 99

# 雙卡 layer split
CUDA_VISIBLE_DEVICES=0,1 llama-bench -m model.gguf -ngl 99 --split-mode layer --tensor-split 1,1

# 雙卡 tensor split
CUDA_VISIBLE_DEVICES=0,1 llama-bench -m model.gguf -ngl 99 --split-mode tensor --tensor-split 1,1

重點看兩列:

  • pp512:prompt processing,長輸入和批量預填充更相關。
  • tg128:token generation,單人聊天和 Agent 體感更相關。

測試時盡量固定模型、量化格式、上下文、batch、驅動版本和 llama.cpp 版本。每組多跑幾次,取中位數,比只看一次結果可靠。最後再用真實工作流跑一遍,例如 Continue Agent、OpenAI-compatible server 或你自己的 RAG 請求,因為 benchmark 好看不代表互動體驗一定更好。

一句話結論

2x V100 16GB 的優勢主要是顯存容量,而不是必然的生成速度。模型單卡能放下時,單張 32GB 往往更快、更穩;模型單卡放不下時,雙 16GB 的價值就很大,因為它能避免大量 CPU offload。至於能不能更快,關鍵看 split mode、batch、模型大小,以及兩張 V100 之間到底是 PCIe 還是 NVLink。

參考資料:

记录并分享
使用 Hugo 建立
主題 StackJimmy 設計