每秒 token 數的物理原理
token 生成速度不神秘:解碼期間,每一個 token 都需要把本質上全部的活躍權重從記憶體讀一次。這讓解碼受記憶體頻寬限制,也代表你可以用除法預測 tok/s。人們爭論的一切——量化、MoE、卸載、批次——都是這條公式戴著不同的帽子。
唯一的公式
tokens/sec ≈ effective memory bandwidth ÷ bytes of weights read per token
RTX 4090, 8B Q4_K_M:
1008 GB/s ÷ 4.9 GB ≈ 205 tok/s theoretical ceiling
observed: ~120–150 tok/s (overhead, attention, KV reads)
一個常見情況的健全性檢查表(Q4_K_M 的 8B、單串流——數量級數字,非規格;自己量):
| 硬體 | ~頻寬 | 預期解碼 |
|---|---|---|
| RTX 4090 | ~1,000 GB/s | ~120–150 tok/s |
| RTX 3090 | ~936 GB/s | ~110–140 tok/s |
| RTX 4060 Ti 16GB | ~288 GB/s | ~35–45 tok/s |
| Dual-channel DDR5 CPU | ~60–90 GB/s | ~8–14 tok/s |
| M3/M4 Max-class Mac | ~300–400 GB/s (unified) | ~40–60 tok/s |
為什麼上限與現實有差距?核心啟動開銷、隨上下文增長的注意力計算、以及權重之外的 KV 快取讀取。公式給你的是上限;單串流通常實現它的 60–75%。
一張卡,四個模型
這條公式也預測固定硬體上模型大小與速度的取捨。約 1,000 GB/s 卡的上限,再算 60–75% 實現(示意):
| 模型 | Q4_K_M 大小 | 上限 | 實際單串流 |
|---|---|---|---|
| 4B | ~2.5 GB | ~400 tok/s | ~230–300 tok/s |
| 8B | ~4.9 GB | ~205 tok/s | ~120–150 tok/s |
| 14B | ~8.5 GB | ~118 tok/s | ~70–90 tok/s |
| 32B | ~19 GB | ~53 tok/s | ~30–40 tok/s |
兩個結論。參數翻倍,同卡速度約減半。而 24 GB 卡上的 32B 對對話而言仍夠快——受記憶體限制不是絕望。這個組合就是 24 GB 卡與 32B Q4 量化版總是成對出現的原因(見 GPU 等級)。
量化是速度功能,不只是壓縮
同一條公式、更少位元組:fp16 的 8B 模型每 token 讀約 16 GB;Q4_K_M 只讀約 4.9 GB。同一張卡上,Q4 的速度約是 fp16 的 3 倍,而且塞得進 fp16 塞不下的地方。這就是 Q4 級量化是本機使用預設推薦的原因(見 量化)——品質損失小,速度收益是結構性的,不是偶然。
上下文會拖慢你
隨對話增長,每個新 token 還要讀之前每個 token 的 KV 快取——那些讀取隨上下文長度縮放。空上下文附近,8B Q4 在 4090 級卡上可能跑 140 tok/s;深入 64k token 的連線後,同樣的設定可能掉到一半或三分之一。注意力核心也不再符合快取友善的形狀。長上下文工作負載正是 flash attention 與 KV 量化回本的地方(見 KV 快取 與 引擎參數)。
常見的困惑:「模型隨對話變慢」通常是 KV 增長,不是伺服器退化(見 KV 快取)。
MoE:以速度換能力
混合專家模型每 token 只啟用少數專家區塊,所以每 token 讀取的位元組追蹤的是活躍參數,不是總量。總量 30B/活躍 3B 的模型在 Q4 下每 token 只讀幾 GB——它帶著大模型的知識、以小模型的速度解碼。這就是 MoE 家族對本機使用的全部吸引力(見 模型家族):你為存放專家付記憶體,但頻寬只付給你用到的。
截至目前具體的形狀:Qwen3-30B-A3B 級每 token 只讀約 3B 活躍參數——大模型知識、小模型速度,Q4 下約 18 GB VRAM。
投機解碼
把小草稿模型與大目標模型配對:草稿便宜地提案 k 個 token,目標在一次前向計算中驗證全部 k 個,被接受的 token 以目標的品質輸出。在接近貪婪的工作負載——低溫下的程式補全、JSON、抽取——預期 2–3 倍解碼加速。高溫時草稿猜錯的機率變高、收益縮水。llama.cpp 透過 --model-draft 與草稿長度旗標提供此功能;確切旗標名隨版本漂移,查 --help。
代價:草稿必須與目標共用分詞器,而且兩個模型都駐留在記憶體。
平行:現實
兩張 GPU 不會給你單串流的 2 倍。張量平行(vLLM -tp 2)把每層拆到多卡換吞吐量,代價是互連流量;llama.cpp 預設的分法是管線(逐層),對容量的幫助大於單串流延遲。好的雙卡拆分現實預期:單串流的 1.2–1.6 倍,不是 2 倍。有人保證每張 GPU 線性擴展,他是在推銷東西。
不過加卡確實能漂亮地擴展容量——那是 並行處理 的伺服器故事。
CPU 卸載懸崖
當層留在 CPU 上,每個 token 的前向計算都要跳過 PCIe(約 10–25 GB/s)到系統 RAM 再回來。迴圈以最慢的駐留部分的速度運行:80% 層在 GPU 的模型,跑起來貼近 CPU 速度,而不是「GPU 速度的 80%」。模型差一點裝得下時,降一級量化,不要半卸載——見 引擎參數。意外部分卸載的明顯徵兆,是 GPU 級硬體上只有 3–10 tok/s。
預填受運算限制:TTFT 是不同的測量
處理提示詞在 token 間平行,受算力而非頻寬限制——4090 級卡能把 8B Q4 預填到每秒數千 tok/s。所以 12k token 的貼文在第一個輸出 token 前要花約 3–5 秒,儘管之後的解碼跑 140 tok/s。首 token 時間與穩態 tok/s 是不同的數字、量的是不同的瓶頸;讀基準測試時,確認它展示的是哪一個。
自己測量
頁面上的數字(包括這一頁)是上限與區間。你的設定兩分鐘就能量:
- 從短提示詞生成約 200 個 token;忽略第一次跑(冷載入)。
- 取穩態解碼:第一個 token 之後的生成 token 數÷秒數。
- 另外記錄長貼文的首 token 時間——那是不同的瓶頸。
llama-server 對每個請求印出 prompt-eval 與 eval tok/s;LM Studio 即時顯示解碼 tok/s;nvidia-smi 在你測試時確認 GPU 真的在忙。
速度的體感
| tok/s | 體感 |
|---|---|
| 5 | 可用但痛苦——你會害怕長回答 |
| 10 | 對話沒問題 |
| 20 | 明快;對話不再像機器 |
| 50+ | 即時;程式助理等級 |
門檻低得驚人,因為人類的閱讀速度只有約 5–10 tok/s——但等一個補全以 5 tok/s 跑是折磨。自己感受:模擬器 以不同 token 速率渲染同一段回答,在那裡一分鐘勝過任何表格。
低於約 2–3 tok/s 時,串流 UI 感覺是壞掉而不是慢——人們會關掉分頁,所以把那當互動使用的硬底線。