讓HERMES寫的報告
vLLM + Qwen3.8-27B-Quark-AWQ-MXFP4 安裝與測試報告
報告日期:2026-09-06 硬體:AMD Radeon AI PRO R9700(RDNA4 / gfx1201 / 32GB VRAM) 容器:vllm-radiance-mxfp4(magiccodingman/vllm-radiance:1.0.15) 服務位址:0.0.0.0:8080
本報告完整記錄在 R9700 上部署 vLLM 並服務 amd/Qwen3.8-27B-Quark-AWQ-MXFP4 模型的整個過程:環境決策、安裝步驟、啟動配置、啟動時間軸、功能驗證、效能基準測試、各種調優實驗的對比結果,以及踩過的坑與最終結論。
1. 背景與決策
目標:在本機 R9700 上以 vLLM 服務 Qwen3.8-27B 的 Quark MXFP4 量化模型(amd/Qwen3.8-27B-Quark-AWQ-MXFP4),並搭配推測解碼(speculative decoding)提升 decode 速度。
關鍵決策:RDNA4(gfx1201)沒有原生 MXFP4 運算單元,通用 rocm/vllm 映像會退回「模擬反量化」(BF16 高精度計算),速度落後 3-5 倍。因此本部署採用社群 fork vllm-radiance(magiccodingman/vllm-radiance:1.0.15,源自 codeberg.org/ggz14/radiance-vllm-mxfp4),它為 gfx1201 實作了原生 MXFP4 W4A8 kernel(RadianceMxfp4W4A8LinearKernel)與 R4D attention 後端。啟動後日誌確認快取路徑全部生效:
Using RadianceMxfp4W4A8LinearKernel for MXFP4 GEMM(W4A8 fp8-WMMA GEMM 啟用)
[radiance] R4D kernel selection: libr4d 全部 query 解析成功
[radiance.gdn] all-R4D prefill / decode(fused) / prefill+spec path live
[radiance] int2 draft head armed(dflash 推測解碼堆疊就緒)
注意:啟動日誌中出現「The current platform does not support native MXFP4/MXFP6 computation」一行是 quark 模組另一支 supports_mx() 呼叫的誤報(上游 repo 文件已註明),不代表 MXFP4 kernel 未啟用;真實狀態以上述 RadianceMxfp4W4A8LinearKernel 行為為準。
2. 環境
項目
值
主機
CachyOS Linux,192.168.1.241
GPU
AMD Radeon AI PRO R9700(RDNA4 / gfx1201 / 32GB VRAM)
容器映像
magiccodingman/vllm-radiance:1.0.15(vLLM 0.28.0 / Python 3.12 / ROCm)
容器名稱
vllm-radiance-mxfp4(2026-09-06 02:19 建立)
主模型
amd/Qwen3.8-27B-Quark-AWQ-MXFP4(19GB,arch qwen3_5,quant_method=quark)
推測解碼 drafter
tcclaviger/Qwen3.8-27B-DFlash2-FP8(2GB,FP8,block 128)
模型存放
/mnt/NVME/qwen38-27b-R9700/models/(bind mount → 容器 /models:ro)
快取目錄
/mnt/NVME/qwen38-27b-R9700/vllm-cache/mxfp4(Triton / inductor / aiter 快取)
啟動腳本
~/vllm-start(start|stop|status|logs)
下游
Open WebUI(8080 串接)+ DSH 使用同一端點
VRAM 使用
34.03 / 34.2 GB(gpu-memory-utilization 0.98 預留,屬正常)
模型權重檢查:config.json 的 quantization_config.quant_method 為 quark、algo_config 為 null(mapper 相容性要求,見第 6 節坑 1);checkpoint 18.44 GiB 單一 safetensors 檔;config.json 保留 config.json.orig_with_algo_config 備份。
3. 安裝步驟
準備 NVMe 目錄:/mnt/NVME/qwen38-27b-R9700/ 下建立 models/、vllm-cache/、ggz14-mxfp4/(radiance repo 的 git clone,含 patches 與 chat template)。
下載主模型 amd/Qwen3.8-27B-Quark-AWQ-MXFP4(19GB)與 drafter tcclaviger/Qwen3.8-27B-DFlash2-FP8(2GB)到 models/ 下。
拉取映像 magiccodingman/vllm-radiance:1.0.15(映像已內建 ROCm、vLLM 0.28.0、libr4d 與 repo patches,無需自建 Dockerfile)。
準備 chat template:ggz14-mxfp4/qwen-fixed-v22.3.jinja(reasoning_effort → Qwen think 控制 token 的映射),以唯讀方式 bind 進容器。
撰寫 ~/vllm-start 啟動腳本(docker run 全參數 + 約 60 個 RADIANCE_* 環境變數),作為唯一權威啟動器(repo 內舊 start-mxfp4.sh 已於 2026-09 刪除,避免誤用過期設定)。
啟動容器:掛載 /dev/kfd、/dev/dri,模型唯讀掛載,快取目錄持久化,端口 0.0.0.0:8080 → 8080。
驗證:/v1/models 回傳 qwen3.8-27b-mxfp4(max_model_len 163840);/v1/chat/completions 冒煙測試成功。
4. 啟動配置
vllm serve 關鍵參數(來自 ~/vllm-start,可調變數在腳本頭部):
參數
值
說明
--kv-cache-dtype
fp8
FP8 KV cache,容量翻倍(需顯式指定,非預設)
--gpu-memory-utilization
0.98
VRAM 預留比例
--kv-cache-memory
7783339733 (7.25 GiB)
顯式 KV 預算,優先於 gpu-memory-utilization
--max-num-seqs
8
短 ctx 爆發用;長 agent 情境建議 2-4
--max-model-len
163840
避免 repo 預設 262144 引發 FLA-GDN OOM
--max-num-batched-tokens
8192
調高至 16384 曾 OOM(見第 6 節坑 5),已固定
--attention-backend
R4D
radiance 原生 R4D attention(僅支援 GQA=6)
--enable-prefix-caching
(啟用)
前綴快取;實測 hit rate 可達 91%
--speculative-config
dflash, spec tokens=7, TRITON_ATTN
DFlash2 FP8 drafter,7 為 block_size 8 的硬上限
--no-async-scheduling
(同步調度)
調優穩定配置;A/B 測試顯示無效能差異(見第 5.4)
--enable-auto-tool-choice + --tool-call-parser
qwen3_xml
工具呼叫解析
--reasoning-parser
qwen3
思考解析(讀 enable_thinking)
--override-generation-config
temp 0.7 / top_p 0.95 / top_k 20
預設採樣參數
--enable-per-request-metrics
(啟用)
基準測試所需的 per-request 直方圖
--chat-template
/chat-template.jinja
reasoning_effort 映射模板
--language-model-only
(啟用)
略過 VLM vision tower
--tensor-parallel-size
1
單卡
環境變數(節選)
RADIANCE_MXFP4=1, W4A8, FAST_DRAFT, DYNAMIC_WIDTH=1, DYNAMIC_DRAFT=1 (schedule 1:8,2:7,4:6,8:5,16:4), DRAFT_TAU=0.20, DRAFT_RERANK=80, USE_R4D=1, GDN 融合系列=1, R4D_ATTN_FP8=0, HF_HUB_OFFLINE=1
完整清單見 ~/vllm-start
5. 測試
5.1 啟動時間軸(2026-09-06 實測)
階段
時間(容器內)
備註
容器啟動
02:19:27
docker run -d
引擎初始化
02:21:04
V1 LLM engine v0.28.0,spec config dflash/spec=7
主模型權重載入
02:21:06 → 02:21:22
18.44 GiB,15.64 秒
drafter 權重載入
02:21:24
1.20 秒
KV cache 配置
02:21:33
180,098 tokens;163,840 ctx 下最大並發 1.10x
CUDA graph 捕獲
02:21:33 → 02:21:37
PIECEWISE 19 組 + FULL 8 組 + dflash2 8 組
API server 就緒
02:22:42
Application startup complete
總耗時
約 3 分 15 秒
權重載入 15.6s 為主
5.2 功能驗證
/v1/models:回傳 qwen3.8-27b-mxfp4,max_model_len=163840。
/v1/chat/completions 冒煙測試:「1+1 等於幾?」→「1+1 等於 2。」,usage 正常(含 reasoning_tokens 統計)。
推測解碼健康:SpecDecoding 指標持續輸出,平均接受長度 2.8-3.0,draft 接受率 26-29%(生產負載下)。
前綴快取:多輪對話 hit rate 達 91.2%。
Open WebUI 串接 8080 正常(容器 healthy)。
VRAM 34.03/34.2 GB 為 0.98 預留設計,非洩漏;分配:權重 19GB + drafter 2GB + KV 7.25GB + 約 6GB workspace。
5.3 基準測試方法
基準協議(~/vllm-bench.py [並發數] [max_tokens] [tag]):固定長 prompt(約 4K tokens 中文段落 x80),N 個相同請求並發,於請求前後對 /metrics 做 delta 取樣:prefill = Δprompt_tokens / Δprefill_time;decode = 1 / ΔTPOT;e2e = Δtokens / Δwall;接受率 = Δaccepted / Δdraft。注意兩點陷阱:(1) 指標是累計值,A/B 比較必須取 delta 或重啟容器重置;(2) 極短 prompt 會低估 prefill(固定開銷主導),必須用長 prompt。
5.4 調優實驗結果
實驗 1 — spec tokens 數(8 並發 / 4K prompt / 128 out,delta 取樣):
指標
spec=7(採用)
spec=5
decode(1/TPOT)
67.1 tok/s
60.6 tok/s
e2e(含 prefill)
181 tok/s
162 tok/s
prefill
2235 tok/s
1747 tok/s
accepted / draft
2.96
2.52
接受率
42.2%
50.5%
結論:不能只看接受率——spec=5 單位接受率較高但每步 draft 位置較少,有效吞吐量反而輸。spec=7 全面勝利,為最終配置。
實驗 2 — 原生 MTP 頭 vs dflash drafter(8 並發 / 4.2K prompt / greedy / 128 out):
指標
MTP spec=3
MTP spec=5
dflash2 spec=7(基準)
decode(1/TPOT)
23.7 tok/s
23.9 tok/s
67.1 tok/s
e2e 吞吐量
82.4 tok/s
55.6 tok/s
181 tok/s
prefill
897 tok/s
913 tok/s
2235 tok/s
draft 接受率
74.7%
59.4%
42.2%
結論:MTP 能跑(Qwen3_5MTP 架構解析成功,需 RADIANCE_QUARK_BF16_MTP=1 讓 BF16 的 mtp.fc 繞過 Quark recipe),但 1 層 MTP 頭每步自回歸跑 N 次,spec 越多浪費越多——比 dflash2 慢約 2.8 倍 decode、2-3 倍 e2e。保留 dflash2 @ spec=7;MTP 僅在需要零外部 drafter 佔用時使用。另 MTP spec=5 在此 KV 預算下無法開機(需要 7.32 GiB > 7.25 可用),spec>=4 需降 max_model_len 至 160000。
實驗 3 — async vs sync 調度(2 並發 / 4K / 128 out):e2e 49.2 vs 49.7、prefill 4330 vs 4366、decode 44.4 vs 44.7、接受率 29.6% vs 29.6%——無可測量差異(先前「async 損失 5-10% decode」的說法未重現;首次 async 跑的 35 tok/s 是 Triton JIT 冷啟動)。維持 --no-async-scheduling。
實驗 4 — 對照上游 repo 預設(ggz14 serve-mxfp4.sh):R4D_ATTN_FP8=0 vs 3 效能相同(e2e 46.9/52.9 vs 46.9/57.9,±10% 為 run-to-run 噪音);GDN fused decode 的 triton fallback 只是 1.0.15 映像層級問題(torch.ops._C.fused_gdn_decode_post_conv_mtp 未編入),非環境變數可修,是相對於 repo 融合路徑的主要 decode 效能差距。其餘參數(TP=1、KV 7.25 GiB、163840、SANITIZE=1、DRAFT_TAU=0.20)皆合理。
實驗 5 — 新增 Quark 模型的兩個坑(Fable / Qwen3.6 MoE 實測):(1) algo_config 非 null 會使 Quark mapper 崩潰(AttributeError: 'dict' object has no attribute 'endswith'),須在 config.json 設為 null(純 mapper 相容欄位,不影響權重品質);(2) R4D 後端寫死 GQA=6,GQA=8 的 MoE 模型須改用 TRITON_ATTN 並關閉 R4D 環境變數。另:MoE 量化模型(Qwen3.6-35B-A3B)在此映像走 on-the-fly 反量化,decode 僅 5.8 tok/s,比 dense 27B+dflash 慢 4-8 倍,已移除不保留。
實驗 6 — reasoning_effort 行為(模板映射實測):off→0 思考 token;low→約 49;high→150(吃光輸出預算,對 agent 危險);max→約 91(反直覺地比 high 少)。模型實際上是 ON/OFF 思考,agent 負載建議 low。注意:把 reasoning_effort 加進 --override-generation-config 無效(不在 available_params 會被靜默丟棄),正確做法是改 chat template 預設值。
5.5 生產負載實測(2026-09-06 07:34 日誌)
指標
值
prompt 吞吐量
454.0 tok/s(長 prompt 請求中)
generation 吞吐量
20.5 - 44.7 tok/s(隨請求類型)
平均接受長度
2.83 - 3.04
draft 接受率
26.1% - 29.2%
KV cache 使用
33.4% - 34.5%
前綴快取 hit rate
91.2%
6. 踩過的坑(按嚴重度)
Quark algo_config 崩潰:config.json 的 quantization_config.algo_config 若非 null,vLLM Quark mapper 在 apply_vllm_mapper 拋 AttributeError(dict 項目被當字串 .endswith 檢查)。修法:設為 null 再重新載入。症狀是引擎在 init 前退出,根因不是 KV/OOM,別先調 163840/FP8。
R4D 後端僅支援 GQA=6:GQA=8 的模型(如 Qwen3.6 MoE)直接 NotImplementedError,須改 TRITON_ATTN 並關 R4D 環境變數。
spec tokens > 7 開機失敗:dflash2 的 draft window 為 8 x (n+1),n=10 時 torch.compile 把該維度特化為常數 88 而標記為 DYNAMIC,torch.fx ConstraintViolationError 使 EngineCore 崩潰。spec=7 是硬上限,清快取重編也無解,須改回 7。
INT4 drafter 無法載入:syvai 的 W4A16 版本是 Marlin pack 量化,linear 權重住在 packed buffer,radiance DFlash loader 要求 dense .weight → AttributeError: 'QKVParallelLinear' object has no attribute 'weight'。需改源碼,維持 tcclaviger FP8。
MAX_BATCHED_TOKENS 調高 OOM:8192→16384 使 activation/workspace 峰值翻倍,在 32GB(權重 19 + KV 7.25 已鎖定)下長 prompt prefill 時 torch.OutOfMemoryError(嘗試分配 860 MiB,0 bytes free)。已回退 8192;要重試須先縮 KV_MEM。
MTP spec>=4 KV 不足:spec=5 需 7.32 GiB KV > 7.25 可用,engine-init 失敗;spec>=4 須降 max_model_len 至 160000。
/metrics 解析陷阱:prometheus 行格式是 name{labels} value,用「名稱+空白」匹配會全部回 0,bench 看似「什麼都沒跑」;要匹配 name{ 或名稱+空白。
sed 刪 --no-async-scheduling 行會吃掉行尾反斜線,docker run 參數列提前結束;必須整行刪除(sed '/--no-async-scheduling/d')。
FP8 KV 未校準:checkpoint 無 q/k scale,vLLM 用 1.0 裸存(log 有 warning);對 27B 推理可接受,但別當已校準 FP8 看待。
「平台不支援原生 MXFP4」日誌為誤報:以 RadianceMxfp4W4A8LinearKernel 行確認真實 kernel 狀態,勿據此判斷 kernel 未啟用。
7. 結論
部署成功:vllm-radiance 1.0.15 + amd/Qwen3.8-27B-Quark-AWQ-MXFP4 + DFlash2 FP8 drafter(spec=7)在 R9700 穩定服務於 8080,啟動總耗時約 3 分 15 秒。
基準效能(8 並發 / 4K prompt / 128 out):e2e 約 47-58 tok/s(spec=7 多請求 delta 實測 181 tok/s)、prefill 約 2000-2300 tok/s、decode 19-23 tok/s(生產負載 20-45 tok/s)、接受率 26-42%。
關鍵配置:KV FP8 顯式指定 + 7.25 GiB 顯式預算、max_model_len 163840、batched tokens 8192、R4D attention、同步調度、dflash spec=7。
已驗證排除的方案:原生 MTP(慢 2.8 倍)、INT4 drafter(無法載入)、MoE 量化模型(慢 4-8 倍)、async 調度(無收益)、batched tokens 16384(OOM)。
已知殘留差距:1.0.15 映像的 GDN 純 decode 步驟走 Triton 未融合路徑(映像層級,需換映像才能修)。
KV 預算現實:180,098 tokens 約等於 1 個 163K 長請求或 8 個 <22K 短請求;agent 長多輪情境建議 max_num_seqs 2-4。