AMD ROCm 上基于 vLLM 部署 Gemma 4 实操手记

最近看到AMD有个开发者计划的活动,提供GPU资源帮助学习LLM的一些知识,因为自己其实用的更多是生物大模型,多半是 transformers、PyTorch 直读开源权重、固定输入输出,和对话型 LLM 的在线 Serving 不是一套逻辑,而常见的商业大模型其实都是作为用户,通过api调用,其实对服务端的一系列工作都没有接触过,所以也想趁着这个机会学习一下。

所以这更像是一篇执行笔记(有一些知识内容的扩展补充):在 AMD ROCm 环境下,用 vLLM 把 Gemma 4 部署成可对外调用的推理服务。

段末注释:ROCm(Radeon Open Compute)是 AMD 的 GPU 计算软件栈;vLLM 是面向生产场景的大模型推理与服务框架,支持 OpenAI 兼容 API、高并发调度与多卡扩展。

这次项目提供了一台 48 GB 显存 的 ROCm 裸金属机器,要求完成「权重下载 → vLLM 起服 → API 验证」这条链路,并为后续微调、评测打底。下面按真实操作顺序展开,每一步遵循同一结构:先说要解决什么 → 再写怎么操作 → 结果里盯什么 → 踩坑与对策


一、课题背景:为什么用 vLLM 做部署?

这一步要弄清什么?

本课题的目标不是「本地跑通一次推理」,而是把模型变成可持续对外提供服务的 API——后续微调完要能无缝接上、多路请求要能调度、业务侧最好能直接用 OpenAI 协议接入。选用 vLLM,正是冲着这类生产向需求去的。

vLLM 的核心优势(和本课题的关系)

能力 说明 对本课题的价值
PagedAttention 分页管理 KV Cache,减少显存碎片 48 GB 卡上跑 E4B 级模型时,显存利用率直接影响能不能起服、能开多长上下文
连续批处理(continuous batching) 动态合并多条请求,提高 GPU 利用率 为多用户 / 多应用共享同一推理服务打基础
OpenAI 兼容 API 暴露 /v1/chat/completions 等标准端点 RAG、Agent、业务代码改 base_url 即可接入
架构覆盖广 持续跟进 Gemma、Qwen、Llama 等新模型 本次 Gemma 4 可直接 vllm serve 加载
可观测性强 启动日志暴露架构、后端、上下文上限等 便于排查 ROCm 环境下的兼容与 OOM 问题
多卡扩展 支持张量并行等 后续若换更大模型,Serving 层可横向扩展

段末注释:KV Cache 是解码阶段缓存历史 token 注意力键值的显存结构;PagedAttention 是 vLLM 用分页方式管理 KV Cache、提升吞吐与显存效率的关键技术。

本次实操目标

一句话概括:在 ROCm 上把 gemma-4-E4B-it 用 vLLM 跑成 OpenAI 兼容服务,并完成 API 冒烟验证。这也是课题后续「微调 → 评测 → 灰度替换」的前置环节。


二、Step 1:确认 GPU 和驱动是否就绪

这一步要解决什么?

在下载十几个 G 的模型之前,必须先确认三件事:

  1. 机器上的 AMD GPU 有没有被系统认出来
  2. ROCm 和驱动版本是什么——后面 PyTorch、vLLM 能不能用,都绑在这上面;
  3. 显存到底有多大、当前干不干净——决定你能跑多大的模型、有没有别人占着的残留进程。

说白了:别急着下模型。硬件都没摸清,后面全是白忙活。

我们做了什么?

AMD 这边看 GPU,相当于 NVIDIA 的 nvidia-smi,命令是 amd-smi

1
amd-smi

部署前 amd-smi:48GB 显存空闲,ROCm 7.2.1

结果里重点看什么?

关注项 本次实测 说明
ROCm 版本 7.2.1 装 PyTorch、vLLM 时要跟它对上
驱动版本 amdgpu 6.14.14 内核态、用户态不匹配容易出怪问题
显存占用 26 / 49136 MB 总容量约 48 GB,当前几乎空闲
温度 / 功耗 31 °C / 26 W 空闲基线,后面加载模型好对比

进程表里几乎没有占显存的任务——说明环境是干净的,可以放心往下走。

可能遇到的问题 & 注意事项

问题 参考对策
命令找不到或报错 检查 ROCm 是否装全;云镜像有时要手动加载内核模块
显存总量和预期不符 云厂商「48G 卡」可能有预留;以 amd-smi 为准做容量规划
已有进程占显存 kill 或换干净节点;生产环境要排查僵尸进程
不知道能跑多大模型 48 GB 大致够 7B~14B 级 BF16/FP16 推理 + 一定 KV 余量;70B 或超长上下文要提前量化或多卡

段末注释:KV Cache 是解码时缓存历史 token 的显存结构,对话越长占得越多。


三、Step 2:确认 PyTorch 能不能真正用到 GPU

这一步要解决什么?

amd-smi 只能说明「硬件在」,还不能说明「你的 Python 代码能跑在 GPU 上」。

vLLM 是站在 PyTorch 上面的。如果 PyTorch 装错了版本——比如误装了 CUDA 版——后面 vllm serve 大概率直接挂。所以这一步的目的很单纯:验证「驱动 → ROCm → PyTorch」这条链是通的

有个容易误会的地方:ROCm 上的 PyTorch 仍然走 torch.cuda 接口(底层是 HIP 兼容),看到 cuda 字样别慌,不代表你装错了 NVIDIA 的包。

我们做了什么?

一行 Python 做探活:

1
python -c "import torch; print('PyTorch:', torch.__version__); print('ROCm available:', torch.cuda.is_available()); print('Device:', torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'N/A')"

PyTorch 2.10 识别到 AMD Radeon Graphics

结果里重点看什么?

  • ROCm available: True —— 这是过关信号,说明 GPU 对 PyTorch 可见。
  • PyTorch: 2.10.0+git8514f05 —— 多半是 ROCm 专用构建,别随手换成 PyPI 默认的 CUDA 版
  • Device: AMD Radeon Graphics —— 设备 0 可用,后续推理会落在这张卡上。

三项都对,才可以进入下载模型环节。

可能遇到的问题 & 注意事项

问题 参考对策
ROCm available: False 九成是 PyTorch 与 ROCm 版本不匹配;换课题方/厂商推荐的 wheel 或镜像
按 NVIDIA 教程装了一堆包仍无 GPU AMD 机器不能照搬 CUDA 安装文档;核对 torch.version.hip
探活过了但 vLLM 仍报错 vLLM 还要单独装 ROCm 构建;三者版本要一起看
团队多人协作环境不一致 把「镜像 + 版本矩阵 + 探活脚本」写进文档,别靠口口相传

建议:把这条探活命令写进部署脚本的 preflight check,每次起服务前自动跑一遍。


四、Step 3:把模型权重下载到本地

这一步要解决什么?

环境没问题了,接下来要备「弹药」——模型权重。

vLLM 吃的是 HuggingFace 风格目录config.json + tokenizer + safetensors),需要确认:

  1. 权重完整下到本地;
  2. 目录结构能被 vLLM 直接读取;
  3. 磁盘空间、下载源速度跟得上。

本次目标模型是 Google 的 gemma-4-E4B-it(指令微调版),体量不小,下载源选对能省不少时间。

我们做了什么?

ModelScope 拉取,并指定缓存目录,避免和代码仓库搅在一起:

1
2
cd /workspace/repo/src/fine-tune/models/gemma4
modelscope download --model google/gemma-4-E4B-it --cache_dir "./models"

ModelScope 下载 gemma-4-E4B-it,主权重约 14.9 GB

结果里重点看什么?

下载完成后,目录里至少应有:

  • config.jsongeneration_config.json —— 模型结构和生成参数;
  • tokenizer.json 等 —— 分词器;
  • model.safetensors —— 主权重,本次约 14.9 GB

看到主权重文件大小合理、进度 100%,就可以准备起服务了。顺便记一下:Safetensors 比老式 .bin 更安全、加载也更快,是现在比较主流的选择。

显存粗算(判断 48 GB 够不够):

[
\text{权重显存(GB)} \approx 2 \times \text{参数量(B)}
]

BF16 下,E4B 量级权重就要吃掉不少显存;后面加载后显存冲到 95%,和这个量级是对得上的。

可能遇到的问题 & 注意事项

问题 参考对策
Hugging Face 直连慢或断 国内优先 ModelScope、hf-mirror 等镜像
下到一半磁盘满了 提前预留 20 GB+ 余量;--cache_dir 指到大盘
只有 GGUF、没有 HF 目录 需先转换为 HuggingFace 格式,或换用支持 GGUF 的推理栈
能下载不代表能商用 Gemma 有使用条款,上线前做法务确认
反复手工下载 生产流水线应固化「模型源 + 校验和 + 缓存路径」

五、Step 4:用 vLLM 把模型起成服务

这一步要解决什么?

权重到位了,核心任务是把模型变成对外可调用的 API 服务。vLLM 的优势在这里体现得最集中:一条 serve 命令即可拉起 OpenAI 兼容端点,背后自动处理模型加载、KV Cache 分配、请求调度与解码。

同时要心里有数:起服不等于「能跑就行」,日志里会告诉你架构有没有认对、上下文上限设了多少、注意力走的哪个后端——这些直接影响后面稳不稳、快不快。

我们做了什么?

1
2
vllm serve ./models/google/gemma-4-E4B-it/ \
--served-model-name gemma-4-E4B-it

--served-model-name 是对外 API 里的模型名,和本地目录路径分开,后面换模型版本会省事。

vLLM 0.23.0 启动日志:识别 Gemma4 架构,max_model_len 131072

结果里重点看什么?

别只看「有没有报错」,日志里这几行值得划重点:

日志信息 说明
Gemma4ForConditionalGeneration 架构识别成功;新模型首发周常遇到「不认识这个架构」
max_model_len: 131072 理论上下文很长,实际能开多少还要看剩多少显存
Forcing TRITON_ATTN backend Gemma4 头维度特殊,强制走 Triton 注意力以保证数值稳定
Asynchronous scheduling is enabled 异步调度开着,有利于吞吐
服务监听 0.0.0.0:8000 默认暴露 OpenAI 兼容的 /v1/chat/completions

看到服务稳定监听、没有 OOM 退出,就可以做下一步验证了。

可能遇到的问题 & 注意事项

问题 参考对策
报「架构未注册」 升级 vLLM 到支持 Gemma4 的版本,或试 nightly
启动时 OOM --max-model-len 缩短上下文;或换量化权重、多卡张量并行
装了 CUDA 版 vLLM 在 AMD 上跑 必须用 ROCm 构建,和 Step 2 的 PyTorch 一起看
K8s 里 Pod 反复重启 大模型冷启动慢,readiness 探针超时别设太短
裸奔 8000 端口上线 生产要挂 Nginx/Ingress,加 TLS、限流、鉴权
客户端写死模型路径 served-model-name 做灰度切换,别绑本地目录

六、Step 5:确认模型真的加载进 GPU 了

这一步要解决什么?

服务进程起来,不代表权重一定在 GPU 上——有些配置错误会导致静默跑 CPU,能出字但慢到没法用。

所以还要再查一次显存:加载前后对比,确认模型吃进去了多少、还剩多少余量给并发和 KV Cache。这也是判断「这张卡还能不能扛业务流量」的关键依据。

我们做了什么?

再次执行 amd-smi,和 Step 1 的空闲状态对比:

vLLM 运行中显存占用约 46.7 GB / 49.1 GB

结果里重点看什么?

  • 显存:从 26 MB 涨到 46,680 / 49,136 MB,约 95% —— 说明权重确实进了 VRAM。
  • 进程:PID 1231927 独占约 45.6 GB,基本就是 vLLM 服务进程。
  • 温度 / 功耗:仍不高,说明是「加载完等着接请求」,还没打满推理。

和 Step 1 一对,心里就有数了:这张 48 GB 卡跑 Gemma 4 E4B,几乎没有余量,并发一上来很容易顶满。

可能遇到的问题 & 注意事项

问题 参考对策
显存几乎不涨 怀疑 CPU offload 或设备映射配错;查 vLLM 启动参数和日志
显存 >90% 还上大并发 设告警;缩短 max_model_len,或 AWQ/GPTQ 量化
单卡已满还想扩容 多卡张量并行、换更大卡、或换更小/量化模型——这是架构决策,不是调个参能糊弄
只看进程在、不看显存 养成「起服后必跑一遍 smi」的习惯

七、Step 6:对话冒烟,验证 API 真能用的

这一步要解决什么?

前面都是「服务活着」。最后还要证明:请求能进来、模型能想、字能出去

冒烟测试的目的:

  1. 验证中文对话、分词、解码全链路正常;
  2. 确认对外模型名 gemma-4-E4B-it 和 API 路径没问题;
  3. 留一份 baseline 输出,后面微调、换模型好对比。

注意:冒烟通过 ≠ 可以上线扛流量,但能拦住一大批「服务起了其实不能用」的低级错误。

我们做了什么?

用 vLLM 自带客户端连本地服务:

1
vllm chat --url http://localhost:8000/v1 --model gemma-4-E4B-it

测试提示词:你是谁,介绍下

vllm chat 中文对话:Gemma 4 自我介绍

模型用中文结构化自我介绍,报出 Gemma 4、能力范围和知识截止——说明链路通了。

日志里有个小提示:argument 'url' is deprecated。CLI 参数会变,自动化脚本最好锁定 vLLM 版本,或改用当前推荐的 --base-url

等价的 HTTP 冒烟(方便接 CI):

1
2
3
4
5
6
7
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gemma-4-E4B-it",
"messages": [{"role": "user", "content": "用一句话介绍你自己"}],
"max_tokens": 128
}'

业务代码侧通常这样接:

1
2
3
4
5
6
7
8
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
resp = client.chat.completions.create(
model="gemma-4-E4B-it",
messages=[{"role": "user", "content": "你是谁?"}],
)
print(resp.choices[0].message.content)

结果里重点看什么?

  • 能稳定返回、中文不乱码、内容符合模型人设 → 基本过关。
  • curl 和 Python SDK 两条路径都过 → 更接近真实业务接入。
  • 记下首条回复当 baseline → 微调前后才有可比性。

可能遇到的问题 & 注意事项

问题 参考对策
CLI 能聊,HTTP 404/422 核对 base_url 是否带 /v1model 名是否和 served-model-name 一致
首 token 很慢 冷启动正常;生产要考虑预热或保活
冒烟过了就以为能上线 还要压并发、长上下文、多轮对话;看 P99 延迟而不只是 QPS
后面要接 RAG / Agent 同一 base_url 可直接给 LangChain、Open WebUI 等用

八、串起来看:整条链路长什么样?

把前面几步摞在一起,完整链路可以看成下面这张图。绿色实线框是本文已走完的实操;灰色虚线框是同一课题里后续还要做的环节,这次记录里尚未展开。

AMD ROCm + vLLM 部署全流程:绿色为本次实操,灰色为后续计划

生图关键词(流程图):科普漫画风格竖向流程图;中文节点;AMD ROCm 48GB → amd-smi → PyTorch 探活 → ModelScope 下载 Gemma 4 → vllm serve → 显存复核 → 冒烟验证 → 微调 → 评测 → 灰度换模型;Step 1~6 绿色实心框「本次已完成」,后续三步灰色虚线框「后续开展」;白底扁平插画,公众号技术配图。

本次已执行(Step 1~6)

顺序 环节 做了什么 状态
环境 申请 AMD ROCm 48GB 开发者计划裸金属,ROCm 7.2.1 ✅ 本文环境
Step 1 amd-smi 确认驱动、显存约 48 GB、环境干净 ✅ 已执行
Step 2 PyTorch 探活 torch.cuda.is_available() 为 True ✅ 已执行
Step 3 ModelScope 下载 gemma-4-E4B-it,主权重约 14.9 GB ✅ 已执行
Step 4 vllm serve OpenAI 兼容服务监听 8000 端口 ✅ 已执行
Step 5 amd-smi 复核 显存占用约 95%,确认权重在 GPU ✅ 已执行
Step 6 vllm chat / curl 中文对话冒烟通过 ✅ 已执行

到这里,「权重落地 → 服务可调用 → API 验证通过」 这条最小闭环已经跑通,也是本次公众号文章的主体内容。

后续开展(课题下一步)

顺序 环节 打算做什么 状态
Step 7 微调 在业务数据上继续训练 / 对齐,产出新 checkpoint ⏳ 计划中
Step 8 评测 对比微调前后指令遵循、领域问答、幻觉率等 ⏳ 计划中
Step 9 灰度换模型 用新 served-model-name 或新版本滚动替换,业务无感切换 ⏳ 计划中

这三步和「把模型跑起来」是不同工种:部署解决的是 Serving 能不能用;微调 + 评测解决的是 模型够不够好;灰度替换解决的是 怎么安全上线。后面会在同系列文章里接着写。

文字版速览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
【本次】申请 AMD ROCm 48GB 环境

【本次】Step 1 amd-smi → 硬件 / 驱动 / 显存

【本次】Step 2 PyTorch 探活 → 软件栈是否打通

【本次】Step 3 ModelScope → 下载 gemma-4-E4B-it(~15GB)

【本次】Step 4 vllm serve → 起 OpenAI 兼容服务

【本次】Step 5 amd-smi 复核 → 显存是否真的吃满

【本次】Step 6 chat / curl → 冒烟通过 ← 本文止于此

【后续】微调 → 评测 → 灰度换模型

九、一张表收拢常见坑

阶段 常见问题 怎么处理
环境 ROCm / PyTorch / vLLM 版本对不上 用锁定镜像 + preflight 脚本
环境 误装 CUDA 版依赖 探活 + 看 torch.version.hip
模型 下载慢、中断 ModelScope / 内网镜像 + 校验
模型 许可证踩线 上线前做法务 review
起服 不认识新架构 升 vLLM,盯 Gemma4 支持版本
起服 OOM max_model_len、量化、多卡
运行 显存满、QPS 低 压测调度策略;固定 attention 后端做对比
接入 只测 CLI 没测 HTTP curl + SDK 双路径冒烟
运维 没监控 显存、延迟、队列深度都要采

按本文流程在 ROCm 上走通一遍,至少能拿到一条可复盘、可交接的 vLLM Serving 最小闭环;后续再在此基础上叠微调与灰度发布。


十、写在最后

本次课题把 LLM 部署落到了一条可执行的链路上:

看硬件 → 探活 → 下权重 → vLLM 起服 → 复核显存 → API 冒烟

48 GB 的卡跑 Gemma 4 E4B,显存已经顶到 95%。这也提醒一件事:模型多大、上下文多长、并发多少,最好在下载权重之前就算账,别等服务 OOM 了再救火。

后续将继续记录微调、评测与灰度换模型;更多部署框架背景可参考 00.本地 LLM 部署框架选型与横向对比


本次环境一览

项目 版本 / 规格
GPU 显存 ~48 GB(49136 MB)
ROCm 7.2.1
PyTorch 2.10.0+git8514f05
vLLM 0.23.0
模型 google/gemma-4-E4B-it(ModelScope)
起服命令 vllm serve ./models/google/gemma-4-E4B-it/ --served-model-name gemma-4-E4B-it
-------------本文结束感谢您的阅读-------------