單張R9700 AI PRO 32G + VLLM + amd/Qwen3.8-27B-Quark-AWQ-MXFP4
-
@paul-hou profill速度怎么那么快 是因为量化等级小吗
-
@paul-hou profill速度怎么那么快 是因为量化等级小吗
还是前缀缓存命中了?
-
之前本地佈署都是靠著網站上的大神們的分享
這個假日測了整整二天VLLM,最終使用了這個方案,結果不錯分享一下。https://github.com/magiccodingman/vllm-radiance
模型
- 主模型:/models/amd/Qwen3.8-27B-Quark-AWQ-MXFP4(served name: qwen3.8-27b-mxfp4)
- Draft 模型:/models/tcclaviger/Qwen3.8-27B-DFlash2-FP8
- 量化:MXFP4(W4A8),RADIANCE_MXFP4=1 + 全套 radiance 優化旗標(WPERM、HOIST_QUANT、EPIFAST、SKINNY_GEMM、R4D attention 等)
引擎參數
- tensor-parallel-size: 1(單卡 R9700 / gfx1201)
- gpu-memory-utilization: 0.98
- kv-cache-dtype: fp8,--kv-cache-memory 7,783,339,733 bytes(~7.3GB 固定分配)
- max-num-seqs: 8
- max-model-len: 163,840
- max-num-batched-tokens: 8,192
- attention-backend: R4D(+ RADIANCE_USE_R4D_GDN / R4D_AR / R4D_AR_QUANT)
- speculative decoding: dflash,num_speculative_tokens=7,TRITON_ATTN,disable_padded_drafter_batch
- mamba-cache-mode: align
- prefix caching: 啟用
- no-async-scheduling
- tool call: qwen3_xml parser;reasoning parser: qwen3
- override generation config: temperature 0.7 / top_p 0.95 / top_k 20
- chat template: qwen-fixed-v22.3.jinja(掛載為 /chat-template.jinja)
- language-model-only、trust-remote-code、HF_HUB_OFFLINE
實際運行狀態(/metrics)
- KV cache:288 blocks,共 180,098 tokens 容量,fp8
- prefix cache 命中率:1.85M / 2.44M ≈ 75.9%
- dflash spec decode:48,588 draft tokens → 17,180 accepted,整體接受率約 35%;position 0 接受率 69%(4920/7108),逐位遞減到 position 6 約 15%
- 目前 0 running / 0 waiting,KV 使用率 0%
- AITER:只啟用 UNIFIED_ATTENTION,其餘(MHA/MOE/MLA/RMSNORM/FP4BMM/FP8BMM)全關
Prefill(長 context 預填)速度:
prompt 長度 實際 tokens TTFT prefill 速度 8K 7,470 3.22s 2,319 tok/s 32K 29,742 11.49s 2,589 tok/s 64K 59,409 17.95s 3,311 tok/s 128K 118,772 45.52s 2,609 tok/s Prefill 穩定在 2,300-3,300 tok/s,128K context 約 45 秒完成預填。
併發測試(每路 max 256 tok):
併發路數 wall time 總輸出 聚合速度 單路速度 1(先前) - 298 tok 41.5 tok/s 41.5 2 7.5s 459 tok 61.4 tok/s 29-34 4 8.7s 982 tok 113.5 tok/s 25-42 8 12.7s 1,941 tok 152.4 tok/s 27-42 實際在DSH的使用,單路思考時是很穩定在40 t/s左右,編程時會到70~80 t/s
,比起llama.cpp + UD-Q4_K_XL 思考時25~40t/s,編程時50~75 t/s 效能好上不少。 -
讓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。



