AMD Instinct MI50(gfx906)上为 Qwen 系列模型优化并可用的 vLLM 相关仓库、Docker 镜像与实践指南。
直接结论
- 有针对 MI50(gfx906)优化过的 vLLM fork / Docker 容器和使用指南,可以跑 Qwen 系列(如 Qwen-7B、Qwen-14B,甚至 Qwen3.6-27B 的示例)。主要基于 ROCm + PyTorch(ROCm) + patched vLLM 的组合。
关键资源(推荐先看)
- Kausik-A/qwen3.6-27b-mi50-vllm(实战 Docker + vLLM 针对 MI50 的工程)
https://github.com/Kausik-A/qwen3.6-27b-mi50-vllm - MI50 专用完整指南(ROCm 安装、PyTorch、Transformers、实测技巧)
https://github.com/RaffaeleSpezia/local-llm-inference-lab/blob/main/MI50 LLM Inference — Complete Guide (ROCm).md - gfx906 / vLLM 的 Docker 镜像示例(参考)
https://hub.docker.com/r/christopherlin/vllm-gfx906 - ROCm 官方关于 vLLM 的生态/文档(参考与兼容性说明)
https://rocm.docs.amd.com/projects/ai-ecosystem/en/latest/inference/vllm.html
ROCm / PyTorch / 兼容性要点
- MI50 最稳妥的 ROCm 版本是 ROCm 6.2 或 6.3(后续一些 ROCm 版本已不再支持老卡)。
- 使用 ROCm 6.2/6.3 对应的 PyTorch for ROCm wheel(或 Docker 镶嵌好的镜像)以保证兼容。
- 许多社区 fork 对 vLLM 做了针对 gfx906/MI50 的补丁(attention 内核 fallback、HIP/Triton 调整、量化兼容等)。
性能与注意事项
- MI50(Vega 架构)通常没有 bfloat16 支持,建议用 fp16。
- 原生 FlashAttention 支持有限,社区实现会回退到基于 HIP/Triton 或优化的 GEMM/分页注意力实现,性能不如最新 NVIDIA 卡但对中小模型(7B/14B)是可用且实用的。
- 对于大模型(如 27B),需使用量化(GGUF 的 Q4/Q5/Q6 系列)并调内存/分页策略以避免 OOM。
- 推荐通过社区 Docker 配置快速复现(镜像通常包含 ROCm、pytorch-rocm、patched vLLM、示例 .env 与 docker-compose)。
快速示例命令(用于验证与启动)
- 启动(以仓库自带 docker-compose 为例):
docker compose up - 验证 MI50 是否可见:
rocminfo | grep MI50
我已打开并查看了 Kausik-A/qwen3.6-27b-mi50-vllm 仓库里的 docker-compose.yml(里面包含了启动 vLLM 在 MI50 上常用的挂载、环境变量与命令)。下面给你一套"拷贝即用"的启动步骤 + 常见故障排查与解决办法(中文)。按顺序做即可。
一、前置条件(必须)
- 主机上已安装并正确启用 ROCm 支持 MI50(建议 ROCm 6.2/6.3,对 MI50/gfx906 最稳定)。内核模块 amdgpu/rocm 正确加载,能看到 MI50。
- 主机上已安装 Docker(建议 Docker Engine)并允许容器访问 /dev/kfd 与 /dev/dri(docker 需要能访问 GPU 设备)。
- 有足够磁盘:模型文件(GGUF)+ triton cache 可能需要几十 GB(视模型大小而定)。
- 准备好 Qwen 的 GGUF/权重文件并放到一个目录(将作为 MODEL_DIR 挂到容器里)。
- 推荐把 triton / vllm 缓存设置为宿主机持久化目录(第一次编译内核会很久,大约 15--30 分钟)。
二、克隆仓库
(在你主机上)
- 克隆仓库:
git clone https://github.com/Kausik-A/qwen3.6-27b-mi50-vllm.git
cd qwen3.6-27b-mi50-vllm
三、准备 .env(示例)
在仓库根目录创建 .env,示例内容(按你环境改路径和值):
VLLM_IMAGE=kausik/vllm-gfx906:latest
CONTAINER_NAME=vllm-mi50
MODEL_DIR=/home/you/models # 里面放 GGUF 权重
HF_CACHE_DIR=/home/you/hf-cache
TRITON_CACHE_DIR=/home/you/triton-cache
VLLM_CACHE_DIR=/home/you/vllm-cache
RENDER_GID=44 # video 组 GID,见下方如何查
VLLM_LOGGING_LEVEL=INFO
HF_TOKEN_VALUE= # 如果需要从 HF 下载 tokenizer/config,写 token;若全部已缓存可留空
HSA_VISIBLE_DEVICES=0 # 如果只有一块 MI50,通常设 0
HIP_VISIBLE_DEVICES=0
ROCR_VISIBLE_DEVICES=0
MODEL_FILE=qwen3.6-27b.gguf # 容器内 /models/${MODEL_FILE}
TOKENIZER_ID=qwen-qwen3.6-7b-tokenizer # 举例,根据模型实际 tokenizer 改
HF_CONFIG_PATH=/models/qwen_config.json
PORT=8080
MAX_MODEL_LEN=8192
GPU_MEMORY_UTILIZATION=0.95
CPU_OFFLOAD_GB=32
说明:
- MODEL_DIR:放 GGUF 文件与可选的 hf config/tokenizer 文件(或把 tokenizer 用 HF 缓存挂载)。
- RENDER_GID:可用命令查 video 组 gid: getent group video | cut -d: -f3
- HSA/HIP/ROCR_VISIBLE_DEVICES 用于在多卡机上 pin 设备;单卡通常都设为 0。
四、挂载/目录准备(宿主机)
- mkdir -p /home/you/models /home/you/hf-cache /home/you/triton-cache /home/you/vllm-cache
- 把 GGUF 模型(例如 qwen3.6-27b.gguf 或 qwen-7b.gguf)放 /home/you/models。
- 把 tokenizer/config 的文件也放到 HF_CACHE_DIR(或确保 HF_TOKEN 可访问 HF)。
五、启动容器
- 在仓库目录运行:
docker compose up
(或后台运行: docker compose up -d)
注意:首次启动会编译 Triton/torch-inductor 内核,时间可能很长(docker-compose.yml 注释里写约 15--20 分钟,复杂模型可能更久)。
六、验证 GPU 与 环境(容器内)
若容器已启动但想验证:
- 打开 shell:
docker exec -it ${CONTAINER_NAME} /bin/bash - 检查 ROCm 可见性:
rocminfo | head -n 40 - 检查 PyTorch for ROCm / GPU 显示:
python -c "import torch; print('hip:', getattr(torch,'version').hip if hasattr(torch,'version') else None); print('cuda_available:', torch.cuda.is_available()); print('device_count:', torch.cuda.device_count())"
(如果输出表明 cuda_available True 且 device_count>=1,则 PyTorch/ROCm 在容器中可用)
七、访问 vLLM 服务
- 浏览器或 curl 访问: http://主机IP:8080/ (端口如 .env 指定)
- 若使用 API,参考仓库 README 的 vllm serve API 使用方法。
八、常见问题与排查(按问题查找)
- 问题:容器启动日志显示"找不到 AMD 设备 / No ROCm device found / cannot open /dev/kfd"
- 排查:
- 主机上执行 rocminfo 是否能看到 MI50?(若看不到,说明 ROCm/驱动问题)
- 查看容器是否有访问 /dev/kfd 与 /dev/dri(docker-compose 已挂载,但宿主机需要存在这些设备): ls -l /dev/kfd /dev/dri
- 确保容器以能访问 GPU 的权限运行(compose 已加 devices 与 cap_add 与 seccomp=unconfined)。如仍报权限,尝试加 privileged: true(临时),或确认宿主机 udev 权限与 video 组。
- 解决:修复主机 ROCm 驱动,或为容器授予访问 /dev/kfd 的权限;确认 RENDER_GID 与宿主视频组一致。
- 问题:PyTorch 在容器内报错或 torch.version.hip 不存在 / torch.cuda.is_available() 为 False
- 排查:
- 在容器内运行 python import torch; print(torch.version, torch.version.hip)
- 检查容器镜像是否与主机 ROCm 版本兼容(镜像里可能是 ROCm 6.3 的 torch,主机如果是 5.x 或 7.x 就会不兼容)。
- 解决:使用与主机 ROCm 匹配的镜像或在主机上安装匹配的 ROCm。通常最简单是采用仓库推荐的镜像并确保主机 ROCm 版本相同(6.3)。
- 问题:第一次非常慢 / 卡在"compiling triton kernels"很久
- 说明:首次将 triton/tensor kernels 编译到 TRITON_CACHE_DIR,时间可能 10--30 分钟(docker-compose.yml 注释)。
- 解决/建议:
- 把 TRITON_CACHE_DIR 指向宿主持久目录并挂载(已在 compose 中配置)。保持缓存以便重启加速。
- TRITON_COMPILE_MAX_WORKERS、TORCHINDUCTOR_COMPILE_THREADS 可调(compose 已设置为 8)。
- 如果有多台机器,可把编译好的 cache 复制过来以跳过编译。
- 问题:模型加载失败(找不到 tokenizer、报 KeyError visual.*)
- 原因:Qwen 家族 GGUF 有不同架构(可能包含视觉 tower),默认 vLLM 可能尝试加载 conditional generation head。
- 解决:compose 已在 command 中加入:
--hf-overrides '{"architectures": "Qwen3_5ForCausalLM"}'
确保你在 .env 中正确设置 TOKENIZER_ID 与 HF_CONFIG_PATH 并把 tokenizer config 放到 HF_CACHE_DIR 或 MODEL_DIR。若从 HF 下载,设置 HF_TOKEN。
- 问题:OOM(显存不足)或启动时报 GPU 内存不足
- 处理办法:
- 减小 GPU_MEMORY_UTILIZATION 值(例如 0.85 或 0.8)
- 增加 CPU_OFFLOAD_GB(把一部分权重放到 CPU)
- 使用量化模型(GGUF 的 Q4/Q5/Q6),换用更小的模型(7B/14B)
- 开启更 aggressive 的 CPU offload / kv cache offload(vLLM 参数可调)
- 问题:FlashAttention / Triton 在 gfx906 上报错
- 说明:gfx906 没有原生 NVIDIA FlashAttention,仓库通过 Triton/HIP fallback 或自实现 kernel。
- 处理:
- 确认环境变量 FLASH_ATTENTION_TRITON_AMD_ENABLE 已设 TRUE(compose 已启用)
- 查看容器日志,若有编译失败信息,尝试清空 triton cache 并重启(有时是编译过程中临时错误);或降低 TRITON_COMPILE_MAX_WORKERS 以减小并发编译压力。
- 若不可恢复,改用非 FlashAttention 实现(在 vLLM 启动参数里禁用 triton flash path,或使用仓库说明的 fallback)。
- 问题:HF 下载失败或 token 问题
- 若你没把 tokenizer/config 放缓存目录且 HF_TOKEN 为空,容器会尝试访问 HF。
- 解决:把 HF_TOKEN 写入 .env(HF_TOKEN_VALUE=xxx),或提前将 tokenizer/config 下好放到 HF_CACHE_DIR,或把 HF_HUB_OFFLINE=0 改成 1 并确保文件都在缓存里。
八、查看日志(关键)
- 查看实时日志:
docker logs -f ${CONTAINER_NAME} - 若容器没启动或崩溃,先 docker compose up(不带 -d)观察输出。
- 常见日志关键词:rocminfo、HIP、No devices found、Triton compile error、OOM、gguf loader error、KeyError visual
九、进入容器进行手动调试命令汇总
- 进入容器:
docker exec -it ${CONTAINER_NAME} /bin/bash - 检查设备:
rocminfo
/opt/rocm/bin/rocminfo - 检查 PyTorch 可见性:
python -c "import torch; print(torch.version.hip if hasattr(torch,'version') else None, torch.cuda.is_available(), torch.cuda.device_count())" - 直接尝试 vllm 命令行加载模型(在容器内):
vllm serve /models/{MODEL_FILE} --tokenizer {TOKENIZER_ID} --hf-config-path ${HF_CONFIG_PATH} --hf-overrides '{"architectures": "Qwen3_5ForCausalLM"}' --dtype half --enforce-eager
(可加 --log-level debug 观察更详细信息)
十、性能调优小技巧
- 使用量化 GGUF(Q4/Q5/Q6)以节省显存并提升吞吐。
- 调整 GPU_MEMORY_UTILIZATION 与 CPU_OFFLOAD_GB 平衡显存/CPU IO。
- 把 TRITON_CACHE_DIR 持久化并使用较多 CPU 编译线程用于第一次编译以后能更快启动。
- 对于高并发场景,调整 vLLM 的 batching / worker 数量。
十一、如果仍然卡住(我可以帮你做的)
- 如果你把主机 ROCm 版本、docker 镜像名(VLLM_IMAGE)、.env 内容发过来(敏感 token 可脱敏),我可以:
- 帮你检查 .env 是否有明显配置错误;或
- 基于你的主机 ROCm 版本给出一个更匹配的镜像 tag / 修改建议;或
- 根据 docker logs 的具体错误(贴日志)给出精确修复步骤。
总结
- 按上面的准备、配置 .env、确保模型/缓存目录存在并正确挂载、执行 docker compose up 即可启动。首次编译耗时是常态;大多数常见问题来自主机 ROCm 与镜像不匹配、设备权限或模型文件/Tokenizer 配置不匹配。遇到具体日志贴出来,我会一步步定位并给出改法。