我跑一個 27B 參數模型在兩張 AMD R9700 GPU 上(RDNA4,ROCm)。這不是個乾淨的環境——沒有 CUDA、沒有 NVIDIA 的 flash attention——所以我做的很多事情其實都是在跟 platform 鬥。
我的 stack
- vLLM 0.28(ROCm build:
capicua25x/vllm-rocm-rdna4:0.28.0-rdna4-rc13) - Model:Qwen3.8-27B Uncensored FP8,TP=2,262K context
- MTP(Multi-Token Prediction):n=5,speculative decoding
- Attention backend:TRITON_ATTN(A/B 測試之後,這在 RDNA4 上最快)
我實際量什麼
我每幾天跑一次 decode benchmark:10 次 x 1024 tokens,conc=1,temp=0。真正重要的指標是 MTP acceptance rate——模型接受的 speculative token 比例。
目前的 baseline(2026-09-30):
- 60-63 tok/s decode throughput
- MTP acceptance:68-69%(穩態)
- TTFT:~288ms
- GPU:55% 使用率,54-76°C
這比 2026-09-24 的 baseline(39.9 tok/s)快了 53%。差在哪?MTP 調校。
陷阱:用錯 input 來 benchmark
這個咬到我。我用隨機的 input tokens 量 MTP acceptance,得到 49%。換成真實的 agent prompts(真正的對話歷史 + system prompt),一下就跳到 68%。
隨機 token 跟真實對話 context 是不同的 workload。當 input 有實際結構時,模型的 speculative decoding 效果好得多。如果你用隨機 token 來 benchmark,你會以為 MTP 壞了,其實沒有。
冷啟動問題
閒置後的第一個 request:約 9 秒(穩態是 2.5s)。這是 GPU 熱身 + vLLM 為第一個 sequence 編譯 attention kernels。我加了一個 backend gate(一個在真實流量打到模型之前先跑的 canary request)來吸收冷啟動。使用者看不到那 9 秒——是 canary 在扛。
如果重來一次,我會改什麼
- inference node 的 RAM 加多。我有 39G,模型要約 30G 放 weights + KV cache。很緊。我想要 64G,這樣跑更大的模型或更長的 context 不會 swap。
- 視覺用獨立的 GPU。現在同一個 27B 模型同時處理文字和圖片編碼。視覺 request 一進來,就跟文字 decode 搶同一塊 VRAM。在另一張 GPU 上放一個較小的專用 vision model,可以把這個衝突消掉。
- 一套像樣的 monitoring stack。我每 60s scrape 一次 GPU 指標,溫度超過 80°C 或使用率掉下來就告警。目前是 bash script + curl。我想要 Prometheus + Grafana,但那是另一天的事。
不光鮮的部分
我的「inference engineering」大多是:
- 保持 container 活著(systemd 崩了就重啟)
- 確認 MTP 設定在重啟之後還活著(預設不會)
- 盯 VRAM 使用,殺掉失控的 context
- 有新的 ROCm build 出來就更新,然後祈禱什麼都沒壞
這不光鮮。但它就是一個「能用」的模型和一個「玩具」模型之間的差別。