DGX Spark · part 10
[Benchmark] 從 19 到 50 tok/s:我們搶先做了全球首個 Gemma 4 E4B NVFP4 量化
TL;DR
Gemma 4 E4B NVFP4A16 在 DGX Spark 上跑 49.9 tok/s — 比 BF16 快 2.6 倍,GPU 佔用只有 9.8 GB。HuggingFace 上第一個 E4B NVFP4 checkpoint,已上傳 coolthor/Gemma-4-E4B-it-NVFP4A16。
白話版:Gemma 4 E4B 量化
Gemma 4 是 Google 在 2026 年 4 月發布的開源 AI 模型家族,共四種大小:E2B(手機用)、E4B(桌機用)、26B MoE、31B dense。E4B 是桌機等級的 edge 模型 — 手機跑不動,但筆電和工作站輕鬆搞定。它能讀文字、看圖片、聽音訊,支援 128K tokens 的上下文(大約一本 300 頁的書)。
量化(Quantization)是一種 AI 模型壓縮技術。想像把高畫質照片轉成較小的檔案:你損失一些細節,但圖片還是看得清楚,而且載入速度快很多。NVFP4 是 NVIDIA 的 4-bit 量化格式 — 把模型裡每個數字從 16 bit 壓到 4 bit,記憶體用量減少,GPU 處理 token 的速度就更快。
為什麼這很重要?在本機跑 AI 代表不用付雲端 API 費用、資料不會離開你的電腦、也沒有速率限制。但本機模型只有跑得夠快才有用。每秒 19 個 token 的 E4B 太慢,沒辦法即時對話。每秒 50 個 token 的 E4B,就能當一個可用的本機 AI agent。
我在 NVIDIA DGX Spark 上把 Gemma 4 E4B 量化成 NVFP4,然後上傳到 HuggingFace — 這是全球第一個 E4B 的 NVFP4 量化版本。這篇文章記錄了完整的過程:三次失敗的嘗試、依賴衝突的地獄、以及最終的 benchmark 數據。
前言
最好的量化是你差點放棄的那個。三次失敗、兩個依賴衝突、一個前一天才 merge 的 PR — 這就是從 19 tok/s 到 50 tok/s 的路。
這是 Part 9:31B Dense — 7 tok/s 的後續。證明了 dense 模型在 GB10 上撞牆之後,問題轉向:小模型呢?Gemma 4 E4B 有個特殊架構 — Per-Layer Embedding (PLE) — 不是 dense 也不是 MoE。值得測。
E4B 到底是什麼:PLE,不是 Dense,不是 MoE
多數討論叫 E4B「8B 模型」然後就沒了。這漏掉了它有趣的地方。
E4B 用的是 Per-Layer Embedding (PLE):42 層 decoder 每一層都有自己的 embedding table,把完整的 262K vocabulary 映射到 256 維向量。這些 table 很大 — 262,144 × 256 × 2 bytes × 42 層 = BF16 下 5.4 GB — 但它們只做 table lookup,不做矩陣乘法。
每個 token 實際經過 Linear 層的 compute 大約只有 4B 參數。剩下的是查表。
模型總量:15 GB (BF16)
├── PLE embeddings: 5.4 GB(純 lookup)
├── Decoder weights: 4.0 GB(真正的 compute)
├── Word embedding: 1.3 GB(262K × 2560)
├── Vision encoder: 0.5 GB
├── Audio encoder: 0.3 GB
└── 其他: 3.5 GB
這對量化有什麼影響?壓縮 PLE table 省磁碟空間,但不太加速推論 — 因為它們本來就不是 compute 瓶頸。Linear 層才是。
BF16 基線:19.2 tok/s
先跑未量化的基線。E4B BF16 + vLLM:
docker run -d --name gemma4-e4b \
--gpus all --ipc host --shm-size 32gb \
-p 8003:8000 \
-v ~/models/gemma4-e4b-bf16:/models/gemma4-e4b \
vllm/vllm-openai:gemma4-cu130 \
--model /models/gemma4-e4b \
--served-model-name gemma-4-e4b \
--kv-cache-dtype fp8 \
--max-model-len 16384 \
--gpu-memory-utilization 0.75
3 輪,每輪 500 tokens:
| 輪次 | tok/s |
|---|---|
| 1 | 19.2 |
| 2 | 19.2 |
| 3 | 19.1 |
穩定,但慢。餐巾紙算術預測了這個結果:就算只算每個 token 實際讀取的 ~10 GB(PLE lookup + decoder weights),10 GB ÷ 273 GB/s ≈ 37 ms/token ≈ 27 tok/s 理論值。27 和 19 的差距來自 PLE lookup pattern 不如 sequential weight read 高效。
FP8 Online:免費拿到 36 tok/s
在造任何東西之前,先試零成本路線。vLLM 支援 online FP8 量化 — 加一個 flag,BF16 checkpoint 在載入時自動量化:
docker run -d --name gemma4-e4b-fp8 \
--gpus all --ipc host --shm-size 32gb \
-p 8003:8000 \
-v ~/models/gemma4-e4b-bf16:/models/gemma4-e4b \
vllm/vllm-openai:gemma4-cu130 \
--model /models/gemma4-e4b \
--served-model-name gemma-4-e4b \
--quantization fp8 \
--kv-cache-dtype fp8 \
--max-model-len 16384 \
--gpu-memory-utilization 0.75
唯一的改變:--quantization fp8。不需要預量化 checkpoint,不需要 calibration data,不需要額外下載。
| 輪次 | tok/s |
|---|---|
| 1 | 36.0 |
| 2 | 35.9 |
| 3 | 35.9 |
模型載入:11.4 GB(原本 15 GB)。速度翻倍,零額外工作。這就是 80/20 解法。
但能不能再快?
NVFP4 嘗試:版本地獄
NVFP4A16(4-bit weights, 16-bit activations)應該能在 FP8 的基礎上再壓 2x。工具:llm-compressor,vLLM 官方量化工具。
第一次:PyPI 安裝
pip install llmcompressor
from transformers.modeling_utils import TORCH_INIT_FUNCTIONS
ImportError: cannot import name 'TORCH_INIT_FUNCTIONS'
Gemma 4 需要 transformers>=5.5(因為 gemma4 model type)。llm-compressor PyPI 版 0.10.0.1 鎖定 transformers<=4.57.6。兩者不相容。強制升級 transformers 會打爛 llm-compressor 的 internal import。
第二次:--no-deps 繞路
pip install llmcompressor
pip install --no-deps 'transformers>=5.5'
同樣的錯誤。TORCH_INIT_FUNCTIONS 在 transformers 5.x 被移除了。PyPI 版的 llm-compressor 直接 reference 它。
第三次:Git Main
PR #2561 — 4 月 6 日 merge,測試的前一天 — 加了官方 Gemma 4 E4B NVFP4A16 範例並修了 transformers 5.x 相容性。
pip install 'git+https://github.com/vllm-project/llm-compressor.git@main'
pip install --force-reinstall --no-deps 'transformers>=5.5' 'huggingface_hub>=0.30'
pip install torchvision --index-url https://download.pytorch.org/whl/cu130
安裝順序很重要。讓 llm-compressor 先拉完所有依賴,再精準替換 transformers 和 huggingface_hub。另外:Gemma 4 的 multimodal processor 需要 torchvision — 不跑不知道,跑了才噴 Gemma4VideoProcessor requires the Torchvision library。
這次成功了。
NVFP4A16 量化:2 分鐘
工具鏈搞定後,量化本身毫無波瀾:
from transformers import AutoModelForImageTextToText, AutoProcessor
from llmcompressor import oneshot
from llmcompressor.modifiers.quantization import QuantizationModifier
model = AutoModelForImageTextToText.from_pretrained(
"/home/coolthor/models/gemma4-e4b-bf16", dtype="auto"
)
processor = AutoProcessor.from_pretrained(
"/home/coolthor/models/gemma4-e4b-bf16"
)
recipe = QuantizationModifier(
targets="Linear",
scheme="NVFP4A16",
ignore=[
"lm_head",
"re:.*vision_tower.*",
"re:.*audio_tower.*",
"re:.*embed_vision.*",
"re:.*embed_audio.*",
],
)
oneshot(model=model, recipe=recipe)
model.save_pretrained("gemma4-e4b-nvfp4", save_compressed=True)
processor.save_pretrained("gemma4-e4b-nvfp4")
379 個 Linear 層被量化。Sanity check generation:"Hello! It's nice to meet you. What is your name?" — 連貫、正常。
NVFP4A16 是 weight-only 且 data-free。不需要 calibration dataset。ignore 列表跳過 vision/audio encoder 和 embeddings — 這些不是太小就是 lookup table,量化它們沒意義。
結果:49.9 tok/s
docker run -d --name gemma4-e4b-nvfp4 \
--gpus all --ipc host --shm-size 32gb \
-p 8003:8000 \
-v ~/models/gemma4-e4b-nvfp4:/models/gemma4-e4b \
vllm/vllm-openai:gemma4-cu130 \
--model /models/gemma4-e4b \
--served-model-name gemma-4-e4b \
--quantization compressed-tensors \
--kv-cache-dtype fp8 \
--max-model-len 16384 \
--gpu-memory-utilization 0.75
模型載入:9.8 GB(BF16 原本 15 GB,FP8 11.4 GB)。
| 輪次 | Tokens | 時間 | tok/s |
|---|---|---|---|
| 1 | 500 | 10.01s | 49.9 |
| 2 | 500 | 10.01s | 49.9 |
| 3 | 500 | 10.03s | 49.8 |
全貌
| 格式 | GPU 佔用 | tok/s | 相對 |
|---|---|---|---|
| BF16 | 15.0 GB | 19.2 | 1.0x |
| FP8 online | 11.4 GB | 36.0 | 1.9x |
| NVFP4A16 | 9.8 GB | 49.9 | 2.6x |
品質驗證
| 測試 | 結果 |
|---|---|
| 長輸出(1000 tokens) | 49.8 tok/s,無退化 |
| 並發(3 parallel) | 每個 52.7 tok/s,合計 158 tok/s |
| 中文(繁體) | 流暢解釋 BPS 策略 |
| 數學推理 | Put spread 最大獲利/虧損計算正確 |
| 程式碼生成 | Black-Scholes 完整且正確 |
| Structured Output (JSON) | 格式正確 |
| 重複退化(數到 50) | 無重複、無 garbage |
為什麼這很重要:Executor 架構
測試 E4B 的動機不只是 benchmark。是在驗證一個 agent 架構假說:
E4B NVFP4 (50 tok/s, local, 免費)
→ 處理 95% 的 routine agent 任務
→ 讀檔、跑指令、parse output
26B-A4B NVFP4 (52 tok/s, local, 免費)
→ 複雜推理的 fallback
→ 只在 E4B escalate 時出場
兩個模型同時放在一台 DGX Spark 上。E4B 9.8 GB + 26B 16.5 GB = 26.3 GB,剩 ~100 GB 給 KV cache。同時跑時頻寬競爭會把速度拉低(26B 降到 ~31 tok/s,E4B ~18 tok/s)— 但在 sequential executor 模式下每次只有一個跑,各自拿到完整頻寬。
如果 95% 的 agent 操作是 routine(讀檔、執行指令、parse output),用 50 tok/s 的 local 模型跑而不是打 cloud API,省延遲也省成本。需要深度推理的 5% escalate 到 26B — 也是 local,也是免費。
缺的那一塊:E4B 的 tool calling 準確度夠不夠當可靠的 executor。這是下一個實驗。
這次學到什麼
最花時間的事
llm-compressor 版本地獄。三次嘗試、三種不同的失敗模式(TORCH_INIT_FUNCTIONS import、huggingface_hub 不相容、缺 torchvision)。實際量化花了 2 分鐘。依賴解決花了一小時。最後的解法 — 從 git main 裝、force-replace transformers — 只有效是因為 PR #2561 前一天才 merge。
可遷移的診斷經驗
- FP8 online 是 80/20 解法。 在 vLLM 加
--quantization fp8就能把任何 BF16 模型速度翻倍,零額外工作。永遠先試這個。 - PLE 架構量化不一樣。 5.4 GB 的 embedding table 不像 Linear 層那樣受益於 weight 量化。模型大小降幅比預期小(BF16 15 GB → FP8 11.5 GB,不是你對傳統 8B 模型預期的 7.5 GB)。
- 當 PyPI 落後 git main 時,先讓 package 拉完所有依賴,再用
--force-reinstall --no-deps精準替換衝突的包。不要對主 package 用--no-deps— 會漏掉間接依賴。
放之四海皆準的模式
最高槓桿的優化往往是不用換 checkpoint 就能用的。--quantization fp8 之於模型服務,就像 --release 之於編譯語言 — 一個你應該永遠開著的 flag,例外很少。
拿模型
Checkpoint 在 HuggingFace:coolthor/Gemma-4-E4B-it-NVFP4A16
vllm serve coolthor/Gemma-4-E4B-it-NVFP4A16 \
--quantization compressed-tensors \
--kv-cache-dtype fp8 \
--max-model-len 16384
或者用 FP8(不需要額外下載):
vllm serve google/gemma-4-E4B-it \
--quantization fp8 \
--kv-cache-dtype fp8 \
--max-model-len 16384
同系列文章:Part 7:Gemma 4 26B-A4B 52 tok/s · Part 8:vLLM vs Ollama · Part 9:31B Dense — 7 tok/s
常見問題
- Gemma 4 E4B NVFP4 在 DGX Spark 上跑多快?
- 49.9 tok/s,NVFP4A16 量化 + vLLM。比 BF16 的 19.2 tok/s 快 2.6 倍。FP8 online 量化介於中間,36.0 tok/s。
- Gemma 4 E4B 的 PLE 架構是什麼?
- Per-Layer Embedding(PLE)讓 42 層 decoder 各自有一個 262K vocabulary 的 embedding table。這些 table 很大(BF16 下 5.4 GB),但只做 lookup 不做矩陣乘法。每個 token 實際跑的 compute 只有 4B 參數,雖然總參數是 8B。
- 可以用 llm-compressor 量化 Gemma 4 E4B 嗎?
- 可以,但截至 2026 年 4 月必須從 git main 裝(不是 PyPI)。PyPI 版本鎖定 transformers<=4.57.6,但 Gemma 4 需要 transformers>=5.5。PR #2561 加了官方 E4B NVFP4A16 範例。
- 有現成的 Gemma 4 E4B NVFP4 checkpoint 嗎?
- 有。HuggingFace 上的 coolthor/Gemma-4-E4B-it-NVFP4A16 是第一個 E4B NVFP4 checkpoint。用 vLLM 搭配 --quantization compressed-tensors 即可使用。