Qwen3.8-27B-FP8 部署实录:AMD MI300X 上跑通 vLLM
适用环境:阿里云 PAI-DSW 实例(ModelScope 环境,实例规格 DSW-AMD,单卡 AMD Instinct MI300,192GB 显存,ROCm 生态)。 文中所有【实测】内容来自 2026-09-28 在该实例上完整跑通的部署,每条命令都可直接复制到 JupyterLab「终端」执行,全程约 20 分钟(下载约 3 分钟、首次启动约 4 分钟)。 推理引擎的原理与选型依据,见本站另一篇文章:vLLM 大模型部署指南:原理、显存与选型。
快速总览(5 步)
- 环境自检(2 分钟)——
rocm-smi确认 GPU / ROCm / vLLM 就绪 - 下载模型到 NAS —— 30.9GB,实测 3 分 14 秒(82 个文件)
- 读取模型配置 —— 确认原生上下文上限,决定
--max-model-len - 启动 vLLM 服务 —— 一键脚本后台启动,实测从启动到 API 就绪约 4 分钟
- 验证服务 ——
/v1/models+ 真实对话 + KV Cache 分配检查
本次实测时间线(从执行启动脚本到服务可用):
| 时间点 | 事件 |
|---|---|
| T+0s | 执行脚本,EngineCore 启动 |
| T+14s | 29.38 GiB 权重全部加载进显存(NAS 页缓存已预热) |
| T+33s~3min | torch.compile 编译(Dynamo 转换 15.33s,编译合计 124s)+ 多模态显存剖析 + KV Cache 分配(引擎初始化合计 208.62s) |
| T+~4min | API 路由注册 → HTTP 服务就绪 |
0. 服务器配置(本次实测)
| 项目 | 配置【实测】 | 部署相关含义 |
|---|---|---|
| GPU | 1× AMD Instinct MI300 系列(gfx942 架构,芯片 ID 0x74b6),显存 205,822,858,888 字节 ≈ 192GB HBM3,功耗墙 650W | 一切显存预算的基数;gfx942 原生支持 FP8 |
| CPU / 内存 | 23 vCPU / 200Gi(可用 198Gi) | 加载与预处理充裕 |
| 系统盘 | 591G(可用 561G) | |
| NAS | /mnt/workspace、/mnt/data | 模型跨实例共享 |
| 软件栈【实测】 | ROCm 7.2.53211、torch 2.10.0rc(ROCm 版)、vLLM 0.28.0、Python 3.12 | 全部预装,无需安装任何东西 |
AMD 卡的两条铁律
- 这是 AMD 卡,走 ROCm/HIP 而不是 CUDA——没有
nvidia-smi,代之以rocm-smi; - 不要再执行
pip install vllm——会拉 CUDA 版把预装环境搞坏。
两个常规提醒
- 实例有时长限制:顶部「单次实例剩余时长」到点自动停机;NAS 数据保留,服务需用第 5 步脚本重新拉起。
- 模型放
/mnt/workspace(NAS):跨实例、跨重启不丢。
1. 环境自检
打开 JupyterLab → 启动页 →「Terminal」,逐条执行。
1.1 确认 GPU(AMD 用 rocm-smi,不是 nvidia-smi)
rocm-smi作用:确认 GPU 可见、驱动/ROCm 正常、功耗与温度。
实测返回(Concise Info 表):
Device Node Ids Temp Power Partitions SCLK MCLK ...
0 1 0x74b6 47.0°C 164.0W NPS1, N/A, 0 982Mhz 900Mhz ... PwrCap: 650.0W VRAM%: 0% GPU%: 0%输出说明:设备 0,芯片 ID 0x74b6,当前功耗 164W / 上限 650W,VRAM 占用 0%。
✅ 验证理由:GPU 可见、温度功耗正常,驱动链路健康。
1.2 确认显存总量与占用
rocm-smi --showmeminfo vram实测返回:
GPU[0] : VRAM Total Memory (B): 205822858888
GPU[0] : VRAM Total Used Memory (B) : 299610112输出说明:总显存约 205.8GB(≈192GiB HBM3),当前仅占用 ~286MB。
✅ 验证理由:显存接近全空,vLLM 启动时能拿到完整的显存预算;205.8GB 这个数字就是后面所有参数计算的基数。
1.3 确认显卡架构(决定量化方案)
rocminfo 2>/dev/null | grep -iE "marketing name|gfx9|chip id" | head -6实测返回:
Marketing Name: Intel(R) Xeon(R) Processor ← 这是 CPU 条目(容器内的通用名)
Name: gfx942
Chip ID: 29878 (0x74b6)
Marketing Name: amdgcna-amdhsa-gfx942:sramecc+:xnack-输出说明:gfx942 是关键——这是 AMD Instinct MI300 系列的指令集架构代号,vLLM/ROCm 对它的支持最完善,且原生支持 FP8 计算。
✅ 验证理由:架构代号决定了两件事——能用 FP8(MI300 系可以,A10 那种 Ampere 卡不行)、AWQ/GPTQ 的内核路径与 NVIDIA 不同。选型前必须先看这一行。
1.4 确认 torch / vLLM / 磁盘
python3 -c "import torch; print(torch.__version__, torch.version.hip, torch.cuda.is_available())"
python3 -c "import vllm; print(vllm.__version__)"
df -h / | tail -1 ; free -h | head -2 ; nproc实测返回:
2.10.0rc11bbd260 7.2.53211 True
0.28.0
591G 218M 561G 1% /
Mem: 200Gi 1.2Gi 196Gi 0B 1.8Gi 198Gi
23输出说明:
- torch 2.10.0rc(ROCm 专用构建),
torch.version.hip = 7.2.53211(HIP 运行时版本,等价于 NVIDIA 世界的 CUDA 版本号); torch.cuda.is_available() == True:在 ROCm 构建上这个 API 同样可用,返回 True 说明 PyTorch → HIP → 显卡链路已打通;- vLLM 0.28.0 预装且为 ROCm 版,无需也不应再 pip 安装;
- 磁盘 561G 可用、内存 200Gi、23 vCPU。
✅ 验证理由:与 NVIDIA 实例相同的判据——is_available()==True + vLLM 版本号存在 = 推理链路就绪;区别只是底层从 CUDA 换成了 HIP。
2. 下载模型
nohup modelscope download --model Qwen/Qwen3.8-27B-FP8 \
--local_dir /mnt/workspace/models/Qwen3.8-27B-FP8 \
> /mnt/workspace/logs/dl_qwen38_27b.log 2>&1 &命令说明(逐段拆解):
| 片段 | 含义 |
|---|---|
modelscope download --model <ID> | 从 ModelScope 下载模型仓库(内网直连,速度极快) |
--local_dir <目录> | 下载到 NAS 目录,持久化;中断后重跑同一命令即断点续传 |
> 日志 2>&1 | 进度与报错写入日志文件,不刷屏 |
nohup ... & | 后台运行,终端断开不影响;[1] 9860 为任务号 |
实测返回(完成后查看)
82/82 [03:14<00:00, 2.39s/file]
Snapshot ready at: /mnt/workspace/models/Qwen3.8-27B-FP8
[1]+ Done nohup modelscope download ...完整性验证:
du -sh /mnt/workspace/models/Qwen3.8-27B-FP8实测返回:29G(= 官方实测体积 30.9GB 的十进制口径;du 按 GiB 计)。
✅ 验证理由:Snapshot ready 是 modelscope 的完成标志(82 个文件全部下载并校验);du 体积与 ModelScope API 查到的官方仓库体积一致,说明快照完整。
2.1 读取模型配置,确定上下文上限(FP8 多模态模型特有的一步)
python3 -c 'import json; c=json.load(open("/mnt/workspace/models/Qwen3.8-27B-FP8/config.json")); tc=c.get("text_config",{}); print("text_ctx:", tc.get("max_position_embeddings")); print("arch:", c.get("architectures"))'实测返回:
text_ctx: 262144
arch: ['Qwen3ForConditionalGeneration']输出说明:
- 原生上下文 262144(256K)——注意它不在 config.json 顶层而在
text_config里,直接读顶层会得到None; - 架构为
Qwen3ForConditionalGeneration,且配置里带vision_config/image_token_id等——这是个带视觉能力的多模态模型,vLLM 会为视觉编码器预留显存; - 顶层还有
quantization_config——FP8 量化标记,vLLM 0.28 自动识别。
✅ 验证理由:--max-model-len 不能超过模型原生上限,这一步就是为第 3 步取值提供依据(实测取原生值的一半 131072,见参数说明)。
3. 启动 vLLM 服务
3.1 一键启动脚本(实测方案)
保存为 /mnt/workspace/scripts_local/start_vllm_qwen38_fp8.sh(启动脚本统一放 scripts_local/ 目录;同目录的 start_vllm_qwen38.sh 启动的是微调模型,用本脚本区分开):
cat > /mnt/workspace/scripts_local/start_vllm_qwen38_fp8.sh << 'EOF'
#!/bin/bash
MODEL_DIR=/mnt/workspace/models/Qwen3.8-27B-FP8
# 模型目录不存在时自动重新下载
[ -d "$MODEL_DIR" ] || modelscope download --model Qwen/Qwen3.8-27B-FP8 --local_dir "$MODEL_DIR"
# 杀掉旧服务,避免端口/显存冲突
pkill -f "vllm serve" 2>/dev/null
sleep 3
# 后台启动,日志落盘
nohup vllm serve "$MODEL_DIR" \
--served-model-name qwen3.8-27b \
--host 0.0.0.0 --port 8000 \
--max-model-len 131072 \
--gpu-memory-utilization 0.90 \
--max-num-seqs 64 \
> /mnt/workspace/logs/vllm_qwen38_fp8.log 2>&1 &
echo started
EOF
chmod +x /mnt/workspace/scripts_local/start_vllm_qwen38_fp8.sh
bash /mnt/workspace/scripts_local/start_vllm_qwen38_fp8.sh # 输出 started 即已在后台拉起3.2 参数说明与取值理由(192GB 卡 + 30.9GB 权重)
| 参数 | 实测取值 | 取值理由 |
|---|---|---|
--served-model-name | qwen3.8-27b | API 请求里 model 字段填的名字 |
--max-model-len | 131072 | 原生上限 262144 的一半(128K),对绝大多数应用足够;KV 实在充裕,需要 256K 也可以调到 262144 |
--gpu-memory-utilization | 0.90 | 205.8GB × 0.90 ≈ 185GB 预算:权重 29.4GiB + 激活/多模态预留 → 其余 ~131.7GiB 全给 KV Cache |
--max-num-seqs | 64 | 并发上限。KV 极充裕(见下),64 路都不构成瓶颈 |
显存预算推理:
总预算 205.8GB × 0.90 ≈ 185GB
− 权重 29.38 GiB(vLLM 日志实测)
− 激活/多模态预留(视觉编码器 + 16384 token 的 encoder cache)
= KV Cache 131.7 GiB(vLLM 日志实测)3.3 启动日志关键行解读(实测)
tail -f /mnt/workspace/logs/vllm_qwen38_fp8.log,关键行如下:
(EngineCore pid=13756) INFO ... [spu_model_runner.py:5515] Model loading took 29.38 GiB memory and 13.928980 seconds
(EngineCore pid=13756) INFO ... [interface.py:911] Setting attention block size to 784 tokens to ensure that attention page size is >= mamba page size.
(EngineCore pid=13756) INFO ... [gpu_model_runner.py:6590] Encoder cache will be initialized with a budget of 16384 tokens, and profiled with 1 image items of the maximum feature size.
(EngineCore pid=13756) INFO ... [backends.py:1155] Dynamo bytecode transform time: 15.33 s
(EngineCore pid=13756) INFO ... [core.py:3447] init_engine (profile, create kv cache, warmup model) took 208.62 s (compilation: 124.06 s)
(EngineCore pid=13756) INFO ... [compilation.py:329] Enabled custom fusions: norm_quant, act_quant # [!code highlight]
(EngineCore pid=13756) INFO ... [spu_worker.py:578] Available KV cache memory: 131.7 GiB # [!code highlight]
(EngineCore pid=13756) INFO ... [kv_cache_utils.py:1869] GPU KV cache size: 2,073,046 tokens, Maximum concurrency for 131,072 tokens per request: 15.83x # [!code highlight]
(APIServer pid=13187) INFO ... [launcher.py:551] Detected the chat template content format to be 'openai'.逐行说明:
Model loading took 29.38 GiB:权重从 NAS 装载极快(页缓存已预热;冷启动会慢一些,属正常);attention page size >= mamba page size:说明 Qwen3.8 是注意力 + Mamba 线性注意力混合架构,vLLM 0.28 已自动处理混合状态的分页,无需人工干预;Encoder cache ... profiled with 1 image items:多模态视觉编码器的显存预留,已自动计入预算;torch_compile_cache+compilation: 124.06 s:ROCm 首次启动要编译内核,编译结果缓存在/root/.cache/vllm/(系统盘),第二次启动会明显变快;Enabled custom fusions: norm_quant, act_quant:FP8 量化融合内核已启用——确认服务确实跑在 FP8 上;Available KV cache memory: 131.7 GiB/GPU KV cache size: 2,073,046 tokens:显存预算扣除后的 KV 总量——约 207 万 token;Maximum concurrency for 131,072 tokens per request: 15.83x:128K 满长度请求可同时跑约 16 路。
✅ 验证理由:日志出现 HTTP server started(或用 curl 探测 /v1/models 有返回)即启动成功。本机实测从执行脚本到就绪约 4 分钟(其中编译 124 秒为一次性开销)。
4. 验证服务
三层验证:服务在线 → 真实对话 → 容量评估。
4.1 第一层:模型在线
curl http://127.0.0.1:8000/v1/models实测返回:
{"object":"list","data":[{"id":"qwen3.8-27b","object":"model",
"created":1790590281,"owned_by":"vllm",
"root":"/mnt/workspace/models/Qwen3.8-27B-FP8","parent":null,"max_model_len":131072,...}]}✅ 验证理由:id 与 --served-model-name 一致、root 指向 NAS 上刚下载的目录、max_model_len 与启动参数一致——三项都对上,说明 API 进程活着且加载的正是目标模型、参数生效。
4.2 第二层:真实对话(端到端推理)
curl -s http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"qwen3.8-27b","messages":[{"role":"user","content":"Introduce yourself in one sentence"}],
"chat_template_kwargs":{"enable_thinking":false}}' \
| python3 -c 'import sys,json; d=json.load(sys.stdin); m=d["choices"][0]["message"]; print("REPLY:", m["content"]); u=d.get("usage",{}); print("completion_tokens:", u.get("completion_tokens"))'命令说明:标准 OpenAI Chat 格式;enable_thinking:false 关闭 Qwen 系列的"先思考再回答"模式(简单任务响应快,去掉该字段则默认思考);英文提问是为了避免测试命令里的中文在终端输入时被干扰,模型回答内容不受影响。
实测返回:
REPLY: I am Qwen, a large language model independently developed by
Alibaba Group's Tongyi Lab, ready to assist you with a wide range of tasks.
completion_tokens: 31✅ 验证理由:几秒内返回连贯、切题的回答 → tokenizer → FP8 GPU 推理 → detokenizer → API 全链路通畅;回答自述是通义实验室的 Qwen → 加载的权重正确;31 token 的用量统计正常生成 → usage 链路正常。
4.3 第三层:显存与 KV Cache 容量评估
grep -a "KV cache\|Maximum concurrency" /mnt/workspace/logs/vllm_qwen38_fp8.log | tail -2
watch -n 1 rocm-smi # AMD 上看显存/GPU 占用用这个,不是 nvidia-smi;Ctrl+C 退出实测返回:
Available KV cache memory: 131.7 GiB
GPU KV cache size: 2,073,046 tokens, Maximum concurrency for 131,072 tokens per request: 15.83x输出说明与验证理由:
- 131.7 GiB ÷ 2,073,046 tokens ≈ 68KB/token(该模型混合架构 + GQA 的实际 KV 开销),与显存预算推理吻合;
- 2,073,046 ÷ 131,072 = 15.83,与日志完全一致——并发上限公式就是 KV 总量 ÷ 单请求占用;
- 对比参考:A10 24GB 跑 Qwen3.5-9B 时 KV 只有 25,438 tokens、8K 并发 3.11x——这台卡的 KV 容量大了约 80 倍,这就是 192GB 显存的意义。
4.4 Python 调用(OpenAI SDK)
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8000/v1", api_key="empty")
resp = client.chat.completions.create(
model="qwen3.8-27b",
messages=[{"role": "user", "content": "写一句关于秋天的诗"}],
extra_body={"chat_template_kwargs": {"enable_thinking": False}},
)
print(resp.choices[0].message.content)该模型带视觉能力(vision_config),除文本外也接受 messages 中的 image 内容(OpenAI 多模态格式),vLLM 0.28 已自动支持。
5. 实例重启后如何恢复(一键启动脚本)
bash /mnt/workspace/scripts_local/start_vllm_qwen38_fp8.sh等 2~4 分钟(第二次启动命中 /root/.cache/vllm/torch_compile_cache,编译开销大幅降低),或阻塞等待就绪:
until curl -s http://127.0.0.1:8000/v1/models > /dev/null; do sleep 5; done; echo "服务已就绪"✅ 验证理由:每 5 秒探测一次 /v1/models,返回 200 即 API 已监听,与 4.1 的验证标准一致。
6. 日常运维速查
| 操作 | 命令 |
|---|---|
| 看实时日志 | tail -f /mnt/workspace/logs/vllm_qwen38_fp8.log |
| 查历史日志 | grep -a "关键词" /mnt/workspace/logs/vllm_qwen38_fp8.log |
| 确认服务进程 | pgrep -af "vllm serve" |
| 重启服务 | bash /mnt/workspace/scripts_local/start_vllm_qwen38_fp8.sh(脚本自带杀旧进程) |
| 彻底停止服务 | pkill -f "vllm serve" |
| 看显存/GPU 占用 | rocm-smi(或 watch -n 1 rocm-smi) |
性能参考
MI300X 的 HBM3 带宽约 3.3TB/s,27B-FP8 单流生成速度显著快于 A10 上的 14B-Int4;多并发总吞吐随 batch 上升(continuous batching)。
7. 常见问题排查(AMD 专属问题见 Q1~Q3)
Q1:为什么没有 nvidia-smi? 这是 AMD 显卡,工具是 rocm-smi(状态)和 rocminfo(架构详情)。看显存用 rocm-smi --showmeminfo vram。
Q2:不小心 pip install vllm 了怎么办? ROCm 镜像里预装的 vLLM 0.28.0 是 ROCm 版,pip install vllm 会拉 CUDA 版覆盖依赖。恢复方式:pip install vllm==0.28.0 --force-reinstall(从 ROCm 源),或最稳妥——提前把 site-packages 里 vllm 目录备份。日常不要在这台机器上动 vllm/torch 的 pip 包。
Q3:量化选 FP8 还是 GPTQ/AWQ? MI300X(gfx942)原生支持 FP8 矩阵计算,vLLM 对 FP8 的支持最成熟(本实例日志里 norm_quant, act_quant 融合内核已生效);AWQ/GPTQ 的高效内核(如 Marlin)是 CUDA 专属,ROCm 上路径不同。结论:在 AMD 卡上优先用官方 FP8 版模型。
Q4:启动报 max_model_len cannot be larger than ...?--max-model-len 超过了模型原生上下文。Qwen3.8-27B 的原生上限是 262144(藏在 config.json 的 text_config 里,见 2.1 节),不要超过这个值。
Q5:启动报 CUDA out of memory? 依次尝试:--max-model-len 降到 65536/32768;--gpu-memory-utilization 调低到 0.85;加 --enforce-eager(省显存,速度略降)。显存被别的进程占用时先 pkill -f "vllm serve"。
Q6:第一次启动很慢正常吗? 正常。实测首次启动含 124 秒内核编译(ROCm 特有),日志会写 torch_compile_cache 目录;缓存落在系统盘 /root/.cache/vllm/,同一实例第二次起明显变快。
Q7:curl 返回 model not found? 请求里的 model 字段必须与 --served-model-name 完全一致(本例 qwen3.8-27b),不确定就查 /v1/models 的 id 字段。
Q8:想换 Qwen3.8-Flash-Next 或 2.4T-A95B? 这台 192GB 单卡装不下:Flash-Next-FP8 185.5GB 塞进去后 KV 几乎为零(不可用),Flash-Next BF16 360GB、2.4T-A95B 任何精度都远超。需要更大实例(多卡 192GB×N)。
Q9:想从自己电脑访问服务? 用 PAI-DSW 控制台「自定义服务」映射 8000 端口或 SSH 隧道,并务必加 --api-key sk-你的密钥 防止裸奔。
相关文章
- vLLM 大模型部署指南:原理、显存与选型 —— 推理引擎原理、KV Cache 显存管理与模型/精度选型的完整讲解
- NebulaGraph 介绍与服务器 Docker 部署 —— 另一篇服务器部署实测记录