LLM Deep Dive · part 7
[Benchmark] FP16、Q8 怎麼選?RTX 5090 跑 Qwen2.5-7B,Q8 每秒 188.75 token
❯ cat --toc
TL;DR
同一張 RTX 5090 跑 Qwen2.5-7B,Q8_0 吐字每秒 188.75 token,FP16 是 109.67,約 1.72 倍。Q8 全卡 VRAM 取樣峰值中位數是 10,467 MiB,含桌面本身佔用。這個模型我會先選 Q8_0,要省記憶體再往 Q6_K、Q4_K_M 選。讀題速度和實際答題品質要另外看。

前言
下載模型時,同一個名字後面掛著 FP16、Q8_0、Q6_K、Q4_K_M。容量差很多,那速度跟品質呢?我想知道的是:卡上明明放得下 FP16,改抓 Q8 到底划不划算。
這次我拿一份 Qwen2.5-7B-Instruct 的 FP16 GGUF,自己量化出另外三份,全部在同一張 RTX 5090 跑。還不熟這些名字,可以先看量化入門;這篇直接拿實測幫你選。
Q8 吐字更快,讀題則是 FP16 較快
先分清楚兩種速度。讀題是模型把你的輸入讀進去,吐字是開始回答後,一段一段往外產生文字。表裡的 token 是模型處理文字時切出的小片段;tok/s 越大,表示每秒處理得越多。
看這張表時,讀題跟吐字分開比。速度取三次中位數;VRAM 則是每次執行時,整張卡取樣峰值的中位數,包含 Windows 桌面及其他桌面程式。
| 格式 | 讀題 tok/s | 吐字 tok/s | 全卡 VRAM 取樣峰值(MiB) |
|---|---|---|---|
| FP16 | 16,447.2 | 109.67 | 16,877 |
| Q8_0 | 15,953.6 | 188.75 | 10,467 |
| Q6_K | 13,175.0 | 231.49 | 8,835 |
| Q4_K_M | 15,407.2 | 284.71 | 7,471 |
我最在意的吐字,Q8_0 是 FP16 的 1.72 倍;繼續往下壓到 Q4_K_M,吐字來到每秒 284.71 token。讀題的排序卻是 FP16、Q8_0、Q4_K_M、Q6_K。檔案比較小,沒有讓每個步驟都跟著變快。
權重縮小後,需要搬的資料變少,這可能有助於吐字速度。不過這次沒有拆開量每個 GPU 運算步驟,不能把所有差異都歸因於搬資料。Q6_K 讀題比較慢,我量到了;究竟卡在哪個步驟,這次還沒查。
Q8 的預測分布最接近 FP16,Q4 的差距較大
光看速度還不夠,我也拿同一份英文文章測下一個 token 的預測。這裡有兩個指標:perplexity 看模型猜原文下一個 token 猜得好不好,用這份文字測試時,數字越低越好;KL divergence 看預測機率分布跟 FP16 差多少,越接近零就越像。兩個都不是「答題正確率」。
語料固定為 Wikitext-2 test 的前 32 個區塊,每個區塊用 512-token context。表中的 perplexity 差值,對照直接跑 FP16 的結果;KL 則對照存下來的 FP16 預測資料。
| 格式 | Perplexity | 與直接 FP16 的差 | KL 對儲存的 FP16 logits |
|---|---|---|---|
| FP16 | 6.098206 | +0.000000 | -0.000010 |
| Q8_0 | 6.106598 | +0.008392 | 0.001709 |
| Q6_K | 6.094548 | -0.003658 | 0.004940 |
| Q4_K_M | 6.308980 | +0.210774 | 0.039512 |
量化的三份裡,Q8_0 的 KL 最小。Q6_K 的 perplexity 甚至略低於 FP16,但我不會因此說它比較聰明:猜中原文的下一個 token,跟整份機率分布像不像 FP16,是不同的問題;這份樣本也不長。
FP16 跟自己的儲存資料相比,KL 跑出 −0.000010。真正的 KL 不會是負數,這是接近零的數值估計誤差。儲存資料也有精度損失:工具重建參照時列出的 perplexity 是 6.085444,直接跑 FP16 則是 6.098206。所以我保留原始值,沒有把負數改成零,也沒有混用這兩個 perplexity 基準。llama.cpp 的說明有交代儲存 logits 的格式;logits 就是換算預測機率前的分數。
這個模型先選 Q8,要省容量再往下選
放得下就先用 Q8_0,要再省 VRAM 用 Q6_K,把容量或吐字速度排最前面就試 Q4_K_M;FP16 留給對照實驗,或特別在意讀題速度的工作。
Q8_0 在這次測試裡,吐字比 FP16 快,預測分布也最接近原版。Q6_K 又省一些 VRAM、吐字再快一些,但分布偏移比較多。Q4_K_M 的檔案最小、吐字最快,perplexity 跟 KL 的變化也比較明顯,拿來工作前先用自己的題目試。
這次沒有量長上下文、多人同時使用、中文 perplexity,也沒有跑程式或數學答題。英文樣本的 KL 很小,還不能替這些工作掛保證。
進階:參數、原始紀錄與重跑方式
不讀這節不影響選格式;下面留給想自己重跑、核對數字的人。
三種量化都從同一份 FP16 產生
來源是 bartowski 的 FP16 GGUF,版本固定在這個 revision。下載後先核對檔案的 SHA256,確認與 HF 的 LFS 物件所列的值相同,再用同一個 llama-quantize 產生三份檔案,沒有套 importance matrix,也就是沒有另外用樣本調整量化時各權重的重要程度。這樣不會混進不同製作者的量化做法。
以下是實際命令。執行目錄裡有 model-f16.gguf,llama.cpp 執行檔放在 bin。輪到別的格式時,測速命令只換 -m 後面的檔名。
.\bin\llama-quantize.exe model-f16.gguf model-Q8_0.gguf Q8_0 8
.\bin\llama-quantize.exe model-f16.gguf model-Q6_K.gguf Q6_K 8
.\bin\llama-quantize.exe model-f16.gguf model-Q4_K_M.gguf Q4_K_M 8
.\bin\llama-bench.exe -m model-f16.gguf -p 512 -n 128 -d 512 -b 512 -ub 512 -t 8 -ngl 99 -fa on -ctk f16 -ctv f16 -r 1 -o json
| 項目 | 本次條件 |
|---|---|
| 日期 | 2026-11-11,Asia/Taipei |
| GPU/驅動 | RTX 5090,Windows WDDM,NVIDIA 621.14 |
| CPU/系統 | Ryzen 9 9950X;Windows 11 build 26300 |
| llama.cpp | b12250,commit ae4893a092e060cfbd4979600bf3c1e48a710874,Windows CUDA 13.5 發行檔 |
| 模型參數量 | 7,615,616,512,來自 llama-bench 輸出 |
| 工作量 | 單流、合成 token;prompt 512、generation 128、depth 512 |
| Batch/microbatch/CPU threads | 512/512/8 |
| GPU/attention/KV | -ngl 99、Flash Attention on、K 與 V 都用 F16 |
| 重複方式 | 四輪,整輪丟棄第 0 輪;第 1–3 輪取中位數與範圍;每次命令 -r 1 |
| 其他預設 | 內建暖身開啟;load/lazy mode auto、repack on、不啟用 fit target;其他值留在完整 JSON |
四輪依序正向、反向、正向、反向跑。所有速度欄位裡,最大與最小值差距最多是中位數的 1.32%,沒有超過實驗前訂的 15% 補量門檻。這裡報中位數與範圍,沒有宣稱做過顯著性檢定。
每次都另開測試行程,不經常駐模型服務,所以沒有 serving prefix cache。四種格式也沒有更換執行檔版本,不需要清掉其他服務的編譯快取。每次測試開始前都確認 ComfyUI 佇列空白;若出現其他 compute 行程,或閒置時的 GPU 使用率與記憶體高於門檻,腳本先等。原本的桌面程式保留,這是 Windows 桌面環境的數字。這套測速不包含文字切成 token、挑選輸出 token 的時間,也不等於聊天軟體的完整回應速度。
VRAM 看整卡取樣,檔案大小另外列
測試行程執行時,大約每 0.2 秒用 nvidia-smi 取樣一次。實測前的全卡用量是 2,379–2,403 MiB。WDDM 沒有提供可用的每行程記憶體數字,因此我沒有把全卡用量當成「模型本身佔多少」;取樣也可能漏掉更短的尖峰。
這張表保留三次的最小值、最大值,以及磁碟上的精確 bytes。
| 格式 | 讀題 min–max tok/s | 吐字 min–max tok/s | 全卡峰值 min–max MiB | 檔案 bytes |
|---|---|---|---|---|
| FP16 | 16354.69–16553.35 | 109.604–109.699 | 16862–16887 | 15237853600 |
| Q8_0 | 15950.65–15963.68 | 188.614–188.756 | 10442–10467 | 8098525600 |
| Q6_K | 13028.98–13203.40 | 231.384–231.716 | 8810–8835 | 6254199200 |
| Q4_K_M | 15323.84–15462.58 | 284.697–284.744 | 7410–7471 | 4683073952 |
每輪原始數字包含被丟棄的暖身輪;summary.json保留中位數與範圍使用的陣列。同一個目錄也有每次的 stdout 與 VRAM 取樣,例如 bench-r1-Q8_0.stdout、bench-r1-Q8_0.vram.json。
品質測試共用同一份 FP16 參照
.\bin\llama-perplexity.exe -m model-f16.gguf -f wikitext-2-raw/wiki.test.raw -c 512 --chunks 32 -b 512 -ub 512 -t 8 -ngl 99 -fa on -ctk f16 -ctv f16 --kl-divergence-base fp16-reference.kld
.\bin\llama-perplexity.exe -m model-Q8_0.gguf -f wikitext-2-raw/wiki.test.raw -c 512 --chunks 32 -b 512 -ub 512 -t 8 -ngl 99 -fa on -ctk f16 -ctv f16 --kl-divergence-base fp16-reference.kld --kl-divergence
第二道命令再依序把模型換成 FP16、Q6_K、Q4_K_M。各次都用前 32 個區塊,不是完整 Wikitext-2 test。原始語料 SHA256 是 173c87a53759e0201f33e0ccf978e510c2042d7f2cb78229d9a50d79b9e7dd08。儲存的參照檔是 2,481,815,316 bytes,SHA256 是 3c765b5a27dc4dca897d628d3fb3b2c1b386b36243071424345872cf0e1d88f0。
品質測試的 log 留著 tokenizer 警告:一個長得像控制符號的 token 被標成其他類型,被 loader 自動覆寫。四種格式繼承同一份 FP16 來源的 tokenizer metadata,並使用同一個 loader,我沒有另外改 tokenizer。
FP16、Q8_0、Q6_K、Q4_K_M的原始輸出都有逐區塊結果、不確定度與 KL 統計。品質計算的不確定度,跟測速重跑三次的範圍,是兩種不同的東西。
用 SHA256 對回每一份模型
FP16: 863c978275bca3fdacdde06cbfc1a65f2bd65210bb7ecfd9ded3b24219d81b54
Q8_0: 6925c96c0e9a6af97a81521caf2dd58da9f0fc5f00620c4d131684b872a6908e
Q6_K: 9616f5a674b8d53dd2c8db918e4d8b5f331a4cca342ba2040c47371a73faecf9
Q4_K_M: 246ac71c280bd514575413b01abef9954f9148c011e4a06df643001a0a6b1910
完整 manifest另列語料、參照與執行檔的 hash。Windows 的小型 exe 還會載入實作 DLL,所以不能單靠 launcher 的 hash 認定整套執行檔相同;固定發行版本與 CUDA backend hash 也要一起留。
常見問題
- RTX 5090 跑 Q8 會比 FP16 快嗎?
- 這次 Qwen2.5-7B 單流測試,Q8_0 吐字每秒 188.75 token,FP16 是 109.67;讀題則是 FP16 較快。兩者用同一版 llama.cpp、固定 512-token depth,不能直接推廣到其他模型或長上下文。
- Q8_0、Q6_K、Q4_K_M 該下載哪個?
- 這個模型我會先選 Q8_0;要再省 VRAM 就用 Q6_K,優先考慮容量或吐字速度則試 Q4_K_M。Q8_0 在這份英文樣本的輸出分布最接近 FP16,但這不代表它在你的工作上一定答得一樣好。
接著讀
- 2026-09-20[LLM Deep Dive] 量化實驗室:什麼是量化、怎麼量化、為什麼會有損失
做了一個可以點的量化實驗室。選格式、追一個權重走完四步,看誤差在哪一步生出來——包括兩個我做之前沒搞懂的來源。
- 2026-09-16[LLM Deep Dive] 一個可以點開的模型解剖室:Qwen3、Flash-Next、DeepSeek 內部長什麼樣
點開立方體、展開 48 層、進到單層看功能分區。四個真實模型的官方 config 釘死版本,資料流真的不一樣。這篇講這個網站給你看什麼、怎麼用它讀一個模型。
- 2026-08-04[Benchmark] 一張 5090 跑會說話的 33B 影片模型:MiniMax-H3 從下載到生出第一支片
MiniMax-H3 影音同步生成新手教學。完整版 115 GiB 要四張卡,量化後 31.7 GiB 一張 RTX 5090 就夠。要下載哪些檔、放哪、怎麼設、提示詞怎麼寫。
- 2026-07-23[LLM 深水區] 自己做「層級量化」:只挑那幾張張量動手,把 GGUF 再榨 2.45 GiB
量化不是把整個模型砍成 4-bit。一個 GGUF 裡本來就混著 F16/Q4_K/Q6_K/F32 好幾種精度。這篇用 Laguna 的 attention 換 Q8 當例子,教你怎麼看每張張量的精度、只動該動的那幾張,還有 llama-quantize 的 tensor-type 陷阱。
不想錯過新文章?
訂閱我確保不漏接!
隨時一鍵退訂。