qwen 3.8 27b mxfp4模型:
amd官方模型:https://huggingface.co/amd/Qwen3.8-27B-Quark-AWQ-MXFP4/tree/main
未经审查mxfp4:https://huggingface.co/just1moremodel/Qwen3.8-27B-Uncensored-MXFP4-awq
一、这篇文章最终能得到什么
我这套环境不是为了跑一个“漂亮 benchmark”就结束,而是实际给 Hermes / Agent、代码任务、长上下文项目使用。
最终调优方向:
- 单卡 Radeon AI PRO R9700 32GB;
- Qwen3.8-27B MXFP4;
- FP8 DFlash2 drafter;
- Radiance W4A8 优化 kernel;
- TP=1;
- DFlash SPEC=7;
- 单 Agent 长上下文约 160K;
- Thinking / reasoning 保留;
- Docker 后台运行,SSH 关闭后模型继续工作;
- 代码、JSON、结构化输出速度明显高于普通聊天;
- Hermes调用速度超快,基本无等待,并且速度达到惊人的70+tokens/s
先说一个非常重要的结论:
不要把某一次输出显示 150、170 tok/s,理解成所有 Prompt 都会固定跑到这个速度。
DFlash2 的 speculative decoding 很吃“预测接受率”。同一张 R9700、同一套模型,代码、JSON、聊天、散文的 tokens/s 可以差一倍。
上游单卡 R9700 的公开 BetterBench 数据也有类似现象:
| 类型 | 单卡实测 decode |
|---|---|
| code | 145.2 tok/s |
| JSON | 184.4 tok/s |
| math | 168.6 tok/s |
| file edit | 166.1 tok/s |
| reasoning | 120.8 tok/s |
| chat | 81.4 tok/s |
| prose | 79.0 tok/s |
| 综合 | 137.7 tok/s |
所以本文重点不是教你追一个“最高数字”,而是:
让 R9700 真正走对优化路径,并根据自己的用途,在速度、上下文、显存和稳定性之间找到合适的 shape。
二、我的实测硬件环境
这篇教程基于下面这台机器:
CPU:Intel Core i5-12400
内存:DDR4 64GB
PCIe:PCIe 5.0 x16
GPU:Radeon AI PRO R9700 32GB
功耗:约 210W
系统:Ubuntu Desktop 26.04
容器:Docker
目标模型:Qwen3.8-27B MXFP4
Drafter:Qwen3.8-27B-DFlash2-FP8
vLLM:Radiance
当前使用镜像:
stilldeadcode/vllm-radiance:0.9.3
当前上游项目:
https://github.com/GGZ14/vllm-mxfp4
README 当前推荐 clone:
git clone https://codeberg.org/ggz14/radiance-vllm-mxfp4
截至本文整理时,上游 README 标记:
Repo version:0.12.0
Pinned image:stilldeadcode/vllm-radiance:0.9.3
三、为什么不用普通 ROCm + 官方 vLLM 就结束
R9700 属于 RDNA4 / gfx1201。
它当然可以跑 ROCm,但“能跑”与“跑得快”不是一回事。
Radiance 这套项目真正有价值的地方,是针对 RDNA4 做了大量专用优化,包括:
- MXFP4 W4A8 GEMM;
- R4D paged attention;
- GDN 优化;
- FP8 residual stream;
- INT2 draft head;
- DFlash2 speculative decoding;
- 单卡 TP=1 专用 profile;
- KV cache pin;
- compile graph cache;
- cudagraph capture 调整。
简单理解:
普通 vLLM
↓
ROCm 能识别 R9700
Radiance
↓
继续把 R9700 的模型 kernel、attention、draft、KV、graph 调到更适合这张卡
如果只是把模型成功加载进显存,但日志里没有真正使用 Radiance kernel,速度可能差很多。
四、安装前先检查主机
至少确认:
ls -l /dev/kfd
ls -l /dev/dri
两者应该存在。
检查 Docker:
docker --version
docker ps
如果普通用户执行 Docker 没权限:
sudo usermod -aG docker $USER
重新登录后:
docker ps
磁盘建议至少预留几十 GB。上游 Quick Start 会下载镜像、模型和相关文件。
五、第一次安装:建议先完整跑通官方 Quick Start
如果是第一次装,先不要急着上 160K。
cd ~
git clone https://codeberg.org/ggz14/radiance-vllm-mxfp4
cd radiance-vllm-mxfp4
./docker-quickstart.sh
它会完成:
- 主机检查;
- 拉取 Docker 镜像;
- 准备 checkpoint;
- 准备相关 kernel;
- 启动服务;
- 发送测试请求。
也可以拆开:
./setup-mxfp4.sh
./serve-mxfp4.sh
默认 API:
http://127.0.0.1:8080/v1
测试:
curl http://127.0.0.1:8080/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model":"Qwen3.8",
"messages":[
{"role":"user","content":"你好,介绍一下你自己"}
]
}'
六、单张 R9700:优先使用 serve-tp1.sh
Radiance 已经提供单卡入口:
./serve-tp1.sh
不要把双卡 TP=2 参数生搬硬套到单卡。
先检测:
./gpu-detect.sh
正常应该看到类似:
AMD GPUs usable: 1 x Radeon AI PRO R9700
tensor parallel: 1
hardware sig: 1x7551-32624
如果系统里还有 AMD 核显,Radiance 会按显存门槛排除小显存 iGPU。
七、Docker 后台启动:SSH 关闭后继续运行
官方 launcher 支持:
DETACH=1
所以单卡可以:
DETACH=1 ./serve-tp1.sh
这时 Docker 使用 detached 模式启动。
含义:
SSH 断开:模型继续运行
终端关闭:模型继续运行
Ctrl+C 退出 docker logs:模型继续运行
Ubuntu 整机重启:默认不能等同于“模型一定自动恢复”
查看:
docker ps
日志:
docker logs -f vllmmxfp4074
停止:
docker stop vllmmxfp4074
如果你自定义了容器名,比如:
qwen38-mxfp4
则:
docker logs -f qwen38-mxfp4
docker stop qwen38-mxfp4
八、我的实际目录结构
我的 Ubuntu:
/home/syxj/vllm/radiance-vllm-mxfp4
模型:
/run/media/syxj/lexar/vllm/models
启动脚本:
/home/syxj/vllm/启停脚本
Target:
/run/media/syxj/lexar/vllm/models/Qwen3.8-27B-Uncensored-MXFP4-awq
DFlash2:
/run/media/syxj/lexar/vllm/models/Qwen3.8-27B-DFlash2-FP8
这里使用的是我自己的兼容 MXFP4 target。
如果只想复现官方路径,优先使用 setup-mxfp4.sh 准备的官方 checkpoint,不需要和我的 SNAP 名称完全一样。
九、第一优先级:确认 Radiance kernel 真正生效
启动以后:
docker logs qwen38-mxfp4 2>&1 | grep -E \
"RadianceMxfp4W4A8LinearKernel|W4A8 fp8-WMMA|Using R4D backend|linear layers|FORCED ONTO AITER"
我的正常日志:
[radiance.mxfp4] W4A8 fp8-WMMA GEMM ENABLED
Using RadianceMxfp4W4A8LinearKernel for MXFP4 GEMM
Using R4D backend
[radiance.mxfp4] linear layers: 304/304 on our kernel
0 FORCED ONTO AITER
最关键:
304/304 on our kernel
0 FORCED ONTO AITER
如果这一块不对,先解决 kernel,再调 MAXLEN / SPEC / 功耗。
十、看到 native MXFP4 warning,不要只看一行就判断失败
可能会出现:
The current platform does not support native MXFP4/MXFP6 computation.
Simulated weight dequantization...
但 Radiance 后面会安装自己的 W4A8 kernel。
继续看:
W4A8 fp8-WMMA GEMM ENABLED
Using RadianceMxfp4W4A8LinearKernel
如果后面这些正常,说明 Radiance 已经接管。
十一、DFlash2:单流高 Tokens/s 的关键
我的配置:
SPEC_METHOD=dflash
SPEC=7
Drafter:
Qwen3.8-27B-DFlash2-FP8
检查:
docker logs qwen38-mxfp4 2>&1 | grep -E \
"RADIANCE_DYNAMIC_DRAFT|INT2_DRAFT_HEAD|DFlash|running the draft eagerly"
正常:
RADIANCE_DYNAMIC_DRAFT=ON
int2 draft head armed
如果出现:
running the draft eagerly
需要重点检查 DFlash graph。
十二、为什么同一张卡有时 150+,有时只有 80 tok/s
DFlash 的本质不是把模型固定变成“150 tok/s”。
它是:
drafter 一次猜多个 token,target 一次验证;猜对越多,一次 forward 实际得到的 token 越多。
例如同样约 35ms/update:
代码:一次接受 4.6 token
聊天:一次接受 2.7 token
最终 tokens/s 会差很多。
所以:
- HTML / JS / Python 通常更快;
- JSON / file edit 通常更快;
- 自由聊天 / prose 更慢;
- Hermes 复杂 Agent 任务介于中间。
这是 speculative decoding 的正常特征。
十三、SPEC=7 还是 SPEC=5
我主要使用:
SPEC=7
因为主要任务是:
- 代码;
- Agent;
- 文件编辑;
- HTML;
- JSON;
- 工具调用。
如果主要是:
- 普通聊天;
- 长 prose;
- 非结构化中文输出;
建议自己 A/B:
SPEC=5
SPEC=7
其他参数完全不动。
十四、单 Agent 用户:MAXSEQS 不要盲目追大
原来的长上下文配置:
MAXLEN=220000
MAXSEQS=3
CHUNK=2560
SPEC=7
后来改成:
MAXSEQS=1
对我的用途更合理。
MAXSEQS 会影响:
- cudagraph capture;
- Mamba / GDN state;
- scheduler;
- KV 余量;
- 并发请求能力。
如果你的场景:
一个用户
一个 Agent
一张 R9700
没有必要把很多显存浪费在并发上。
十五、CHUNK:Prefill 和显存之间的交换
官方单卡偏吞吐的默认方向:
CHUNK=4096
我的 160K 长上下文:
CHUNK=2048
关系大致是:
CHUNK 大
→ Prefill 快
→ activation 峰值高
→ KV 剩余少
CHUNK 小
→ Prefill 稍保守
→ activation 峰值低
→ 更容易给长上下文留 KV
所以:
65K / 128K,重视 Prefill:
优先 4096
160K,重视长上下文:
可以先从 2048 起
十六、220K 为什么会失败
我最开始试过:
MAXLEN=220000
MAXSEQS=3
CHUNK=2560
SPEC=7
GPU_UTIL=0.98
KV_MEM=0
真实启动日志:
Available KV cache memory: 5.03 GiB
To serve at least one request with max seq len 220000:
7.53 GiB KV cache is needed
estimated maximum model length is 137280
所以这不是“220K 比较慢”。
而是:
在 KV_MEM=0 的 profiling 下,220K 根本起不来。
十七、理解 KV_MEM:0、auto 和显式 pin
这是长上下文最重要的参数之一。
KV_MEM=0
KV_MEM=0
表示强制让 vLLM profiling。
优点:安全、不容易把显存顶死。
缺点:会保守地扣除 transient activation peak、cudagraph 估算和 allocator margin。
KV_MEM=auto
KV_MEM=auto
Radiance 会先查 kv-profiles.tsv。如果当前 hardware signature + shape 有已测 pin 就使用,否则回退 profiling。
KV_MEM=
例如:
KV_MEM=6100000000
直接固定 KV cache bytes。
它可以拿回 profiling 留下的 margin,但必须自己验证稳定性。
十八、不要照抄别人的 KV pin
上游公开过类似单卡 R9700 profile:
1x7551-32624
MAXSEQS=8
CHUNK=4096
MAXLEN=65536
SPEC=dflash
KV=6535819798 bytes
这只能说明单 R9700 的显式 pin 可以高于保守 profiling。
它不代表所有 R9700、所有 MAXSEQS、CHUNK、MAXLEN 都能直接使用同一个值。
KV margin 还受:
- activation peak;
- cudagraph capture set;
- allocator fragmentation;
- checkpoint;
- drafter;
- 软件版本;
影响。
十九、正确做法:运行 calibrate-kv.sh
Radiance 已经提供:
./calibrate-kv.sh
先看计划:
./calibrate-kv.sh --dry-run
快速只做第一阶段:
./calibrate-kv.sh --quick
正式校准:
./calibrate-kv.sh
校准脚本不仅看“KV 分配成功”,还会检查 health、prefill 和 decode,逐步把 pin 推到失败边界再回退。
修改 MAXSEQS 或 CHUNK 后,建议重新校准。
二十、我的 160K 长上下文 shape
目前我的方向:
MAXLEN=160160
MAXSEQS=1
CHUNK=2048
SPEC_METHOD=dflash
SPEC=7
GPU_UTIL=0.98
RADIANCE_GDN_LAZY=0
为什么不是整 160000?
当前 TP=1 日志显示 attention block:
880 tokens
所以:
160160 = 880 × 182
当前我的机器使用过:
KV_MEM=6100000000
并成功运行。
但请注意:
6100000000 是我的机器上的工作值,不是所有 R9700 的万能参数。最终以自己 calibrate-kv.sh 的结果为准。
二十一、一个适合分享复现的 160K 启动 Wrapper
假设:
项目:/home/你的用户名/vllm/radiance-vllm-mxfp4
模型:/mnt/models
创建:
start-vllm-longctx.sh
内容:
#!/usr/bin/env bash
set -euo pipefail
BASE="/home/你的用户名/vllm/radiance-vllm-mxfp4"
MODELS="/mnt/models"
SNAP="$MODELS/Qwen3.8-27B-Uncensored-MXFP4-awq"
DRAFTER="$MODELS/Qwen3.8-27B-DFlash2-FP8"
export RUNTIME=docker
export IMAGE="stilldeadcode/vllm-radiance:0.9.3"
export NAME="qwen38-mxfp4"
export PORT=8081
export MODELS
export SNAP
export DRAFTER
export MAXLEN=160160
export MAXSEQS=1
export CHUNK=2048
export SPEC_METHOD=dflash
export SPEC=7
export GPU_UTIL=0.98
# 示例值:正式使用请换成自己校准结果
export KV_MEM=6100000000
# 多轮聊天不要打开 lazy GDN
export RADIANCE_GDN_LAZY=0
# 长上下文 shape 单独 cache
export CACHE="$HOME/.radiance-cache-w4a8-093-longctx-160k-s1-c2048"
# Docker 后台运行
export DETACH=1
exec "$BASE/serve-tp1.sh"
权限:
chmod +x start-vllm-longctx.sh
启动:
./start-vllm-longctx.sh
二十二、为什么 RADIANCE_GDN_LAZY=0
上游已经把 lazy GDN 默认关闭,因为多轮聊天中出现过重复循环、空回复和状态损坏。
所以 Hermes / OpenAI-compatible 多轮聊天建议:
RADIANCE_GDN_LAZY=0
不要为了省一点状态显存主动改成 1。
二十三、Thinking 没有因为提速被关掉
我的配置没有:
--disable-thinking
enable_thinking=false
thinking=false
日志仍会看到:
reasoning_parser=qwen3
chat_template=/patches/qwen-fixed-v22.3.jinja
如果出现:
Model Runner V2 does not yet support the thinking_token_budget request parameter
它只是表示 V2 Runner 不支持“按请求设置 thinking token budget”,不等于 Thinking 被关闭。
我的原则:
提速归提速,不靠关闭 Thinking 来作弊。
二十四、不同 shape 建议用不同 Compile Cache
不要让:
65K / 8 / 4096
128K / 8 / 4096
160K / 1 / 2048
220K / 3 / 2560
全部共用一个 cache。
建议:
~/.radiance-cache-w4a8-093-tp1-throughput
~/.radiance-cache-w4a8-093-longctx-160k-s1-c2048
如果修改过 traced graph 相关配置,旧 cache 可能重放旧 graph。
二十五、160K 以后还有没有空间
有,但建议小步提高:
160160
↓
166320
↓
176K 左右
↓
180400
↓
有余量再考虑 192K
每升一档:
- MAXSEQS 不变;
- CHUNK 不变;
- SPEC 不变;
- 重新校准 KV;
- 冷启动;
- 固定 Prompt 测试;
- 再跑真实 Agent 多轮任务。
不要从 160K 直接跳回 220K。
二十六、GPU_UTIL 不建议继续硬顶
当前:
GPU_UTIL=0.98
已经比较激进。
不建议为了几十 K 上下文直接改:
GPU_UTIL=0.99
优先级应该是:
MAXSEQS
→ CHUNK
→ KV calibration
→ MAXLEN
→ 最后才考虑 GPU_UTIL
二十七、210W 和更高功耗怎么选
不要简单理解:
300W > 210W,所以所有任务都更快
更高功耗可能对 prefill、多并发 aggregate throughput 更有帮助,但单流 decode 不一定同比例提升。
我的主要场景是 Hermes / Agent / 单用户 / 长时间运行,所以目前更倾向:
210W + 稳定
二十八、PCIe 3.0 x16 会不会严重拖慢
我的机器就是 PCIe 5.0 x16。
模型完整驻留显存以后,单流 decode 第一瓶颈通常不是 PCIe,而更可能是:
- GPU kernel;
- VRAM bandwidth;
- attention;
- GDN;
- DFlash 接受率;
- context length。
PCIe 更明显影响模型加载、offload 和多卡搬运。
二十九、模型放 EXFAT 外置盘,会不会拖 Tokens/s
我的日志显示:
Filesystem type: EXFAT
Auto-prefetch is disabled
它主要影响冷启动和 checkpoint 读取。
模型进显存后,一般不会决定持续 decode tok/s。
所以:
启动慢 ≠ 模型生成慢
三十、启动成功后我必看的命令
容器
docker ps --filter name=qwen38-mxfp4
Health
curl http://127.0.0.1:8081/health
模型信息
curl http://127.0.0.1:8081/v1/models
Radiance kernel
docker logs qwen38-mxfp4 2>&1 | grep -E \
"RadianceMxfp4W4A8LinearKernel|linear layers|FORCED ONTO AITER|Using R4D backend"
DFlash
docker logs qwen38-mxfp4 2>&1 | grep -E \
"RADIANCE_DYNAMIC_DRAFT|INT2_DRAFT_HEAD|draft eagerly|DFlash"
KV
docker logs qwen38-mxfp4 2>&1 | grep -E \
"Available KV cache memory|KV cache|maximum model length"
三十一、如何正确测速
至少准备三个固定 Prompt。
A:代码
从零写一个完整 HTML 俄罗斯方块,CSS 和 JavaScript 全部内嵌,可直接运行。
看 DFlash 高接受率场景。
B:普通中文分析
固定 2K~4K 上下文,测试 prose 和 SPEC=5 / 7。
C:真实 Agent
保持 system prompt、skill、MCP、项目和任务一致。
记录:
TTFT
Prefill tok/s
Decode tok/s
tok/update
任务总耗时
显存占用
是否出现重复/空回复
三十二、常见报错与解决方向
| 现象 | 常见原因 | 处理 |
|---|---|---|
| 220K 启动失败 | KV 不够 | 降 MAXLEN / MAXSEQS,重新 calibrate |
| 日志估算只能 137280 | KV_MEM=0 profiling 保守 | 使用当前 shape 的 KV pin |
| 代码 140+,聊天 80 | DFlash 接受率差异 | 正常,关注 tok/update |
| Hermes 越聊越慢 | 上下文越来越长 | 看 prompt tokens / TTFT |
| 改 shape 第一次很慢 | 新 graph 正在 compile | 正常 |
| 改 shape 后异常 | 复用了旧 compile cache | 换独立 CACHE |
| 304/304 消失 | Radiance kernel 没完整接管 | 查镜像/kernel/cache |
| running the draft eagerly | DFlash graph 失效 | 排查 graph |
| thinking_token_budget warning | V2 不支持预算参数 | 不等于关闭 Thinking |
| 多轮重复或空回复 | GDN lazy 问题 | RADIANCE_GDN_LAZY=0 |
| CHUNK 提高后 OOM | activation peak 上升 | 回退 CHUNK,重校 KV |
| MAXSEQS 提高后 OOM | graph/state/KV 开销增大 | 回退并重校 |
三十三、后台运行、重启、关闭命令
假设容器:
qwen38-mxfp4
启动:
/home/syxj/vllm/启停脚本/start-vllm-longctx.sh
强制按脚本重建:
/home/syxj/vllm/启停脚本/start-vllm-longctx.sh --force
Docker 原参数重启:
docker restart qwen38-mxfp4
停止:
docker stop qwen38-mxfp4
删除:
docker rm -f qwen38-mxfp4
日志:
docker logs -f qwen38-mxfp4
关闭 SSH 不影响 detached 容器。
三十四、如果想让 Ubuntu 重启后自动恢复
SSH 关闭和 Ubuntu 主机重启不是一回事。
如果模型盘在系统启动时一定已经挂载,可以给现有容器设置:
docker update --restart unless-stopped qwen38-mxfp4
查看:
docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' qwen38-mxfp4
但如果模型在 /run/media/... 这种外置盘/桌面自动挂载路径,更稳的方式是:
- 先保证硬盘自动挂载;
- Docker 服务启动;
- 再执行自己的 start-vllm 脚本;
- 用 systemd 管理依赖顺序。
三十五、我不建议再犯的几个错误
- 直接抄别人 220K KV pin;
- 想长上下文却永远 KV_MEM=0;
- 为了提速关闭 Thinking;
- 所有 shape 共用一个 cache;
- 一次改五个参数;
- 只看一次峰值 tok/s;
- 为了 220K 放弃稳定性。
160K 稳定、速度快,实际价值通常高于 220K 勉强启动。
三十六、我目前最推荐的单 Agent 参数
如果用途和我类似:
单张 R9700
一个用户
Hermes / Agent
代码任务
希望上下文尽量长
从这里开始:
MAXLEN=160160
MAXSEQS=1
CHUNK=2048
SPEC_METHOD=dflash
SPEC=7
GPU_UTIL=0.98
RADIANCE_GDN_LAZY=0
KV:
不要照抄万能数字,跑 calibrate-kv.sh。
如果只是想快速验证这套思路,6100000000 是我使用过的一个工作值,但长期使用仍建议自己校准。
三十七、如果更重视吞吐而不是 160K
不要照抄长上下文 shape。
可以更接近官方单卡方向:
MAXLEN=65536
MAXSEQS=8
CHUNK=4096
SPEC=7
KV_MEM=auto
如果提高 MAXSEQS,记得重新校准 KV。
不存在一套同时拥有:
单请求最快
多请求吞吐最高
长上下文最大
TTFT 最低
的万能参数。
三十八、最后总结
如果把这段时间调 R9700 vLLM 的经验压缩成一句话:
先确认所有算子真的走 Radiance 快 kernel,再让 DFlash 多接 token;单 Agent 就把并发资源让给 KV,长上下文靠实际 KV calibration,而不是靠把 MAXLEN 写得特别大。
推荐优化顺序:
1. Radiance kernel 正常
2. R4D attention 正常
3. DFlash2 正常
4. SPEC 与任务匹配
5. MAXSEQS 与真实并发匹配
6. CHUNK 平衡 Prefill 与显存
7. calibrate KV
8. 每个 shape 独立 compile cache
9. 小步提高 MAXLEN
10. 最后再研究更高功耗
对于单 R9700 跑 27B,我目前认为:
160K 左右上下文
+
DFlash2 SPEC=7
+
MAXSEQS=1
+
正确 KV pin
是一档非常值得尝试的配置。
它不一定有“纸面最大的上下文”,但对于真正跑 Agent、代码和长项目,速度、稳定性、上下文三者更平衡。
参考资料
vllm-mxfp4 / Radiance:
https://github.com/GGZ14/vllm-mxfp4当前 README 推荐源:
https://codeberg.org/ggz14/radiance-vllm-mxfp4建议重点阅读:
- README.md
- PERFORMANCE.md
- MXFP4-NOTES.md
- serve-mxfp4.sh
- serve-tp1.sh
- calibrate-kv.sh
- kv-profiles.tsv





