Day 08 開賽前我押過一注。M4 Max 的記憶體頻寬帳面 546 GB/s,4070 Ti 是 504,同一個量級,所以我猜 Mac 會小勝 8% 左右。
開獎那天,兩台跑的是同一顆 Gemma 4 12B 官方 QAT、同一個 llama.cpp release b10488、同一組 -n 128 -r 10 -fa off -ngl 99:
| tg128(tok/s) | |
|---|---|
| T1 M4 Max 128GB · Metal | 40.83 [30.2–41.7] |
| T2 RTX 4070 Ti · CUDA | 57.72 [57.71–57.72] |
中位數 [全距],取多個獨立 process,口徑同 Day 08。T1 那個寬全距來自一筆冷卻不足的 run。
4070 Ti 快 41%。我押的方向跟幅度都錯了。
今天就是要把這 41% 拆開來看。範圍先講清楚:全篇只有 bs=1 的單流 decode——一個人、單發問題、逐字生成,沒有 speculative decoding。批次一拉大規則整套換掉,那是第 3 週的事。
那組數字還有一個形狀:同樣這兩台,prefill 差了 7 倍,decode 只差 1.4 倍。同一組硬體、兩種工作差這麼多,至少很像不是卡在同一個地方。
decode 每產一個 token,GPU 大致都得把這個 token 用得到的權重重新串流一次——矩陣不搬進來就乘不了。而一個 token 份量的矩陣乘,對現代 GPU 來說根本吃不飽。
所以單流 decode 卡的是搬運,不是計算,這種狀況叫 memory-bound。prefill 反過來:同一份權重可以攤給一整批 token 用,搬運成本被攤薄,比較偏吃算力。

圖 1:這個循環每產一個 token 就走一次。
於是有一條可以寫在便利貼上的除法:
單流 tok/s 天花板 ≈ 記憶體頻寬(GB/s)÷ 每個 step 要讀的權重(GB)
分母寫「每個 step 要讀的權重」不是囉唆:dense 做第一階估算,直接拿整份 tensor size 就夠;但 MoE 每個 token 只讀被選中的那幾個 expert 加上一直開著的權重,不能拿整顆 model size 代進去。
那顆 Gemma 4 12B,llama-bench 印出來是 6.48 GiB,換十進位是 6.96 GB(Day 07 那條 GB/GiB 規矩的第二個用場)。
M4 Max 這台:
天花板 546 ÷ 6.96 = 78.5 tok/s
實測 40.83 tok/s
只有天花板的 52%。同一條除法套 4070 Ti:504 ÷ 6.96 = 72.4,實測 57.72,是 80%。
四個數放在同一個刻度上:

圖 2:左邊兩根天花板,Mac 高 8%;右邊兩根實測,4070 Ti 高 41%。
帳面 546 對 504 沒說錯,Mac 的天花板確實高一點。差在兩台把帳面換成 tok/s 的效率——真正在比的不是 546 對 504,是 546 的 52% 對 504 的 80%。這個比例我後面都叫它兌現率。
把同一條除法換個寫法——實測 tg × 權重——就是 Day 08 表頭那個權重讀取等效(weight-equivalent bandwidth):M4 Max 是 284 GB/s、4070 Ti 是 402 GB/s。兩種寫法同一件事,284 ÷ 546 一樣是 52%。
這裡要小心:284 不是 profiler 量到的 DRAM 流量。真實 decode 還要讀 KV cache、activation 與中間 buffer,kernel 裡也有 cache 命中與解量化。這個數只把權重那一筆算進分子,拿來看「這套軟硬體離天花板多遠」剛好,當成硬體規格就過頭了。
換一顆模型再算一次:同一台 M4 Max 跑 Llama-3.1-8B Q4_K_M(4.92 GB),tg 58.39,得到 53%。兩顆很接近,但我不會把 52-53% 當成 M4 Max 的固定常數。
Mac 贏的是容量線,不是速度線。 至少在這組 bs=1 decode 裡是這樣——Day 07 那格 107.5 GiB 對單卡 12 GiB 是真的,速度線則要看兌現率。
前兩個數在同一份 llama-bench 輸出裡:
# ① tg128 那一列就是 tg
# -ngl 99 對本文這幾顆足以 full offload;層數更多的要自己確認
./llama-bench -m model.gguf -n 128 -r 10 -ngl 99 -fa off
# ② 同一張表的 size 欄就是模型大小(GiB)
# 換十進位:GiB × 1024^3 ÷ 1e9
# ③ 天花板 = 帳面頻寬 ÷ 模型大小
# ④ 兌現率 = 實測 tg ÷ 天花板
size 是模型 tensor 的大小,不是 GGUF 檔案大小(檔案還含 metadata 與 tokenizer)。兩者差不多,但你拿 ls 的數字算會跟我對不上。
-ngl 99 與 -fa off 是 Day 08 那六根釘子裡的兩根:沒 full offload 就不是在量這台機器的頻寬,而 -fa 吃 auto 會因 backend 或 build 選到不同路徑。
一台能跑 llama-bench 的機器加一顆 7B/8B 的 Q4 就能驗;要完整重現開頭那張 T1/T2 對照,才需要 Mac 與 N 卡各一台。算出來的兌現率貼留言區,我幫你看健不健康。
先看一組現象。#4167 那串裡有同一台 M4 Max、同一個 commit、只換量化的三列,是全篇少數可以直接相比的資料。

圖 3:同一台機器只換量化,兌現率反而是 Q4_0 最低。
這裡容易誤會:Q4_0 的絕對速度確實最快,83.06 對 F16 的 31.64。但它沒有等比例變快——權重小了 3.5 倍,速度只快 2.6 倍。
差額跑到分母去了。兌現率的分子只算權重,分母卻是整個 decode step 的時間;KV、kernel、解量化都吃這段時間。其中只要有些成本沒有跟著權重一起縮,它們在 Q4 裡的佔比自然就變大。
試著寫成式子:每 token 時間 = 權重 ÷ B + 固定成本。用 Q4_0 與 F16 解,得到 B ≈ 493 GB/s、固定成本 ≈ 4.3 ms。
兩個參數配兩個點本來就一定解得出來,這步沒有資訊量。有意思的是沒有參與擬合的 Q8_0:這組參數預測 53.2 tok/s,實測 54.05,只差 1.5%。
但 B 與固定成本都只是擬合參數,並沒有真的把 kernel、解量化與 cache 的成本分開。而且這組參數不能跨模型、跨 build 直接搬——拿去預測我 2026 build 上的 Gemma 4,算出 54 tok/s,實測只有 40.8。那個「固定」只在這組資料裡固定。
長 context 還會再吃一刀:hardware-corner 的 RTX PRO 6000 資料裡,Llama 3.3 70B Q4 在 4K 是 32.0 tok/s、128K 只剩 16.6。權重一個 byte 沒變,掉的那一半來自長 context 下 attention 與 KV cache 多出來的流量與計算。
我本來想在這裡給你三條可以直接套的「有效頻寬帶」:Metal 幾成、消費卡幾成、機房卡幾成。
它們撐不住。Metal 那條我原本抓 55-65%,把我自己量到的 52% 排在外面;消費卡那條抓 65-85%,看一眼下面這張圖就知道問題在哪。

圖 4:同一張表的五張卡,兌現率從 56% 到 84%,帳面最高的 5090 落在最下面。
這五列共用同一顆 Llama 2 7B Q4_0,也都跑 Vulkan——模型跟 backend 都是控住的。沒控住的是 commit 與各自的測試環境,那串橫跨 220 天。所以它不能拿來排卡的優劣,只說明除以自家帳面之後,兌現率也不會變成硬體常數。能換出多少 tok/s,是硬體架構、backend、kernel、driver、build 與測試環境一起決定的,這張表只固定了其中兩項。
一台機器倒推一次是一個點,點拼不出通則。
所以規劃的時候我不猜成數,直接做 sensitivity。下面這張表想回答的是:如果兌現率落在某個值,70B 會跑多快。
| 假設兌現率 | M4 Max 546 | 4070 Ti 504 | PRO 6000 1,792 | H100 ×2 6,700 |
|---|---|---|---|---|
| 50% | 6.4 | — | 21.1 | 78.8 |
| 60% | 7.7 | — | 25.3 | 94.5 |
| 70% | 9.0 | — | 29.5 | 110.3 |
| 80% | 10.3 | — | 33.7 | 126.1 |
全部是 70B Q4_K_M(42.52 GB)的單流 tok/s。H100 那欄是 TP2 的合計頻寬。
4070 Ti 那欄是空的:單卡 12 GiB 裝不下 42.52 GB 的權重。沒有 full offload,這條除法就不適用——partial offload 之後瓶頸會換成 PCIe 與主記憶體,那是另一本帳。塞不塞得下要先過 Day 09 那一關,才輪得到今天這條除法。
50-80% 不是信賴區間,也不是硬體通則,就是四個 sizing 情境——我自己兩台的 52% 與 80% 剛好是頭尾。拿到自己的 tg 之後,用上一節那條除法把區間收成一個點。
這四個情境有沒有離譜?拿 T3、T4 做個 sanity check。RTX PRO 6000 帳面 1,792,天花板 42.1 tok/s;兩筆明載 Q4 的外部實測約 27 與 32 tok/s,粗估 64% 與 76%。StorageReview 另有一筆 31.7,但沒寫量化,只看速度量級,不算兌現率。
H100 那筆條件齊得多:NVIDIA NIM 官方表列 2×H100 SXM、FP8、TP2、併發 1、500 in/2000 out,52.85 tok/s。拿 NVIDIA 公開那顆 FP8 checkpoint 的 72.66 GB 當權重大小的 proxy(NIM 跑的 engine 未必等於這個檔),算出約 0.57。至少這幾筆都沒有跑到四個情境之外。

圖 5:T1 與 T2 的天花板線幾乎重疊,落點卻差了半個身位。
懶得手算的話,Day 09 那支計算機的工具 3 就是這張圖的互動版,網址在 Day 09 文末。
dense 的 70B Q4_K_M,權重 42.52 GB。M4 Max 帳面 546 全吃滿的話:
546 ÷ 42.52 = 12.8 tok/s
在本文 bs=1、無 speculative 的前提下,這是用帳面 DRAM 頻寬算出的第一階上界。再拿我這次量到的 52% 當一個 sizing 情境,大約 6.7。
我常看到一個數字:「70B 在 M4 Max 上 20-28 tok/s」。把它換回權重讀取等效:20 tok/s 要 850 GB/s、28 tok/s 要 1,191 GB/s,而帳面只有 546。差得不是一點點,所以條件一定有東西不一樣。看到這種數字,第一件事不是相信,是先問四件事:同一顆模型嗎?同一個量化嗎?有沒有開 speculative decoding?量的到底是不是 decode?
明天,Day 11:「70B 上 M4 Max:那些 20-28 tok/s 到底是怎麼來的」——今天這條除法就是明天的第一把尺。
咱們明天見。