mcpField
S
serving-llms-on-instinct

serving-llms-on-instinct

github.com/amd云与 DevOps470916 次安装2 天前更新
代码仓库

关于 serving-llms-on-instinct

用于指导在 AMD Instinct GPU 上部署 vLLM 端点的 skill,面向部署运维人员。它涵盖 GPU 检测、环境验证、模型配置与显存估算,并可指导在本地或远程主机启动和验证服务。

主要功能

  1. 01本地或通过 SSH 检测 GPU
  2. 02验证运行环境
  3. 03读取模型配方与 GPU 覆盖配置
  4. 04估算显存和张量并行需求
  5. 05启动并检查 vLLM 端点

适用场景

  1. 01为 AMD Instinct GPU 准备模型服务命令
  2. 02检查模型是否适配可用显存
  3. 03在远程 GPU 主机启动并验证端点

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/amd/skills --skill serving-llms-on-instinct

安装后在 Claude Code 中输入/serving-llms-on-instinct确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

reference.md
skill-card.md
data/
blacklist.json
gpu_overrides.json
evals/
evals.json
hooks.py
machine.yml
scripts/
detect.py
estimate_vram.py
sync_recipes.py
validate.py

详细介绍

在 AMD Instinct 上提供 LLM 服务

在 AMD Instinct GPU 硬件上运行 vLLM 端点。

前提条件

  • 在 GPU 主机上安装 ROCm 驱动和 amd-smi
  • Docker 正在运行且可访问(使用 docker ps 检查)
  • GPU 主机上存在 /dev/kfd 和 /dev/dri
  • HF_TOKEN 环境变量中设置了 HuggingFace 令牌(门控模型需要;Qwen3 或 Gemma 不需要)。对于门控模型(Llama 3.2、Gemma 等),HF 令牌必须属于已在 huggingface.co/<model_id> 接受该模型许可的账户。有效令牌若未接受许可,将报错“Engine core initialization failed”,且错误信息不明确。
  • 对于远程 GPU:已配置 SSH 密钥访问(运行 ssh <user>@<host> 时不应提示输入密码)。如果只能使用密码访问,请先设置密钥:ssh-copy-id <user>@<host>

数据文件

直接读取这些文件以获取模型和 GPU 配置:

  • data/recipes_cache.json —— 从 vllm-project/recipes 同步的模型配置。每个 models.<HF_ID>.recipe 条目都包含完整的配方,其中有 model.base_args、 model.base_env、features.tool_calling.args、features.reasoning.args、 hardware_overrides.amd.extra_args、hardware_overrides.amd.extra_env。 顶层的 docker_image 字段包含最新解析出的 vLLM ROCm 镜像。

  • data/gpu_overrides.json —— GPU 专属配置。包含 docker_flags(所有 AMD Instinct GPU 都必须设置)、以 gfx_version 为键的 gpu_configs(含 env_defaults 和 workarounds),以及适用于尚未收录到 vLLM 配方中的模型的 legacy_models。

  • data/blacklist.json —— vLLM 配方中无法作为 LLM 端点提供服务的模型。包括扩散/图像/音频生成模型、嵌入模型、重排模型、需要音频管线的 ASR 模型,以及需要尚未发布的 vLLM nightly 版本的模型。尝试提供模型服务前,请先检查此文件。如果用户请求的模型在黑名单中,请说明无法运行的原因并推荐替代方案。

如果用户未指定模型,默认使用 Qwen/Qwen3.5-9B:采用 MTP 的稠密多模态模型,Apache 2.0 许可证(无需 HF 令牌),可在单张 GPU 上运行,具备出色的推理和工具调用能力。

步骤 1:检测 GPU

python3 scripts/detect.py
# Remote:
python3 scripts/detect.py --host user@hostname

返回包含 gfx_version、vram_gb、gpu_count、rocm_version 的 JSON。

gfx_version硬件VRAM
gfx950MI350X / MI355X288 GB HBM3E
gfx942MI300X(192 GB)/ MI325X(256 GB)/ MI300A(128 GB)不定

如果 gfx_version 为 unknown:amd-smi 已运行,但未找到 GPU。请检查 lsmod | grep amdgpu。

步骤 2:验证环境

python3 scripts/validate.py --auto-fix
# Remote:
python3 scripts/validate.py --auto-fix --host user@hostname

返回包含 ready(布尔值)、errors、warnings、fixes_applied 的 JSON。 如果 ready 为 false,请勿继续。

步骤 3:刷新配方(如已过期)

检查 data/recipes_cache.json 中的 fetched_at。如果文件缺失或距今超过 24 小时,请刷新:

python3 scripts/sync_recipes.py

此操作会从 GitHub 浅克隆 vllm-project/recipes,并从 Docker Hub 获取最新的 Docker 标签。耗时约 10 秒。如果失败,现有缓存仍可使用。

步骤 4:构建 Docker 命令

直接读取 data/recipes_cache.json 和 data/gpu_overrides.json。 组合以下内容来构建 Docker 命令:

  1. gpu_overrides.json > docker_flags 中的 Docker 标志(所有 AMD GPU 均为必需项)
  2. HF 缓存挂载:-v ~/.cache/huggingface:/root/.cache/huggingface (如果主机上存在共享模型缓存目录,请检查 models--* 目录是在缓存根目录下,还是在 hub/ 子目录中,然后相应地挂载到 /root/.cache/huggingface 或 /root/.cache/huggingface/hub)
  3. 端口:-p <port>:<port>(默认值为 8000)
  4. 环境变量:将 gpu_configs.<gfx_version>.env_defaults 与配方中的 model.base_env 和 hardware_overrides.amd.extra_env 合并。 始终添加 --env HF_TOKEN=${HF_TOKEN}。
  5. Docker 镜像:使用 recipes_cache.json 顶层的 docker_image (除非模型需要固定版本的镜像,例如 GLM-4.5 需要 v0.15.1)。 如果用户指定了 Docker 镜像版本,请对照配方中的 model.min_vllm_version 检查。如果镜像版本较旧,请发出警告——模型可能会在启动时因含义不明的“Engine core initialization failed”错误而崩溃。
  6. 模型 ID:--model <HF_ID>
  7. vLLM 参数:合并配方中的 model.base_args + hardware_overrides.amd.extra_args + features.tool_calling.args + features.reasoning.args。如果尚未添加,请添加 --enable-auto-tool-choice。 对于多 GPU,添加 --tensor-parallel-size N(请参阅下文的 VRAM 估算)。 对于多 GPU 上运行的 MoE 模型,还需添加 --distributed-executor-backend mp。
  8. 端口参数:--port <port>

如果 recipes_cache.json 中没有完全匹配的模型 ID,请去掉日期/版本后缀,检查是否存在基础模型匹配项(例如,Kimi-K2-Instruct 匹配 Kimi-K2-Instruct-0905)。如果找到,请使用基础模型的配方。

如果没有匹配的配方,请检查 gpu_overrides.json 中的 legacy_models。如果其中也没有,则使用通用配置: --enable-auto-tool-choice --trust-remote-code --tool-call-parser hermes。

精度变体选择: 配方可能提供多个变体(默认、fp8、 nvfp4)。选择变体前,请检查 gpu_overrides.json 中的 gpu_configs.<gfx_version>.precision.native。在 gfx942(MI300X)上,只有 bf16、fp16、fp8_fnuz 和 int8 是硬件原生支持的。MXFP4 和 NVFP4 计算采用模拟方式(矩阵乘期间反量化为 BF16),但权重仍以压缩形式保存在 VRAM 中,因此量化模型仍可在更少的内存中运行。 在 gfx950(MI350X)上,MXFP4 是硬件原生支持的。

VRAM 估算和适配检查: 构造 Docker 命令前,请估算模型是否能在可用硬件上运行:

python3 scripts/estimate_vram.py --model-id <HF_ID> --vram-gb <per_gpu_vram> --tp <N>

此操作会查询 HuggingFace Hub API(不会下载模型),并返回包含以下内容的 JSON:

  • weight_memory_gb——权重总大小
  • kv_cache_bytes_per_token——BF16 下每个 token 的 KV 缓存开销
  • fit.weights_fit——权重是否能在给定的 TP 下装入显存
  • fit.recommended_max_model_len——GPU 可提供服务的最大上下文长度
  • fit.context_limited——如果 KV 缓存导致上下文长度低于模型原生最大值,则为 true
  • fit.min_tp_required——所需的最小 TP(仅当权重无法装入显存时显示)

了解开销: 该脚本会为 vLLM 的运行时开销预留约 4 GB (激活值分析、HIP 图捕获、内部缓冲区)。启动期间,vLLM 会运行一次分析前向传递,以测量峰值激活值,然后捕获 HIP 图以优化解码。此启动峰值高于稳定运行时的峰值。remaining_for_kv_gb 字段反映了扣除权重和此开销后剩余的空间。

使用 remaining_for_kv_gb 来判断:

  1. remaining_for_kv_gb >= 6:可以安全运行。如果 context_limited: true, 在 vLLM 参数中添加 --max-model-len <recommended_max_model_len>。 如果用户需要更长的上下文,提及 FP8 KV 缓存选项(--kv-cache-dtype fp8); fit.max_seq_len_fp8_kv 会显示提升幅度。
  2. remaining_for_kv_gb 在 2 到 6 之间:余量紧张,但值得尝试。正常启动。 如果 vLLM 在 HIP 图捕获期间 OOM(检查容器日志中是否在 "capturing CUDA/HIP graphs" 之后出现 "out of memory"),请在 vLLM 参数中添加 --enforce-eager 后重试。此操作会跳过图捕获并释放 1-2 GB。唯一的代价是 解码延迟略有增加。
  3. remaining_for_kv_gb < 2:余量过于紧张,可能会在激活分析步骤中 OOM。 不要尝试。
  4. 多块 GPU 且 weights_fit: false:使用 --tp <min_tp_required> 重新运行, 并再次检查。
  5. weights_fit: false,且 GPU 数量不足:按以下顺序查找量化替代版本: a. 配方变体:配方可能提供 fp8 或 mxfp4 变体,其 model_id 指向不同的量化检查点。 b. 同一提供方:许多提供方会随基础模型一同发布量化版本(例如 Qwen 提供的 Qwen/Qwen3.5-122B-FP8)。在 HuggingFace 上搜索 <provider>/<model-name>, 并使用 FP8/GPTQ/AWQ 后缀。 c. AMD 量化模型:AMD 的 Quark 团队会在 HuggingFace 的 amd/ 组织下 发布量化模型(例如 amd/Kimi-K2-Instruct-w-mxfp4-a-fp8)。 搜索 amd/<model-name> 变体。 对量化模型 ID 运行 estimate_vram.py,确认显存足够,然后改用该模型 ID。
  6. 仍不满足要求:告知用户该模型所需的 VRAM 超出可用容量,并建议改用更小的模型 或多 GPU 硬件。不要尝试启动。

Docker 命令模板:

docker run -d --name vllm-<model-slug> \
  <docker_flags> \
  -v <hf_cache_mount> \
  -p <port>:<port> \
  --env <key>=<value> (for each env var) \
  --env HF_TOKEN=${HF_TOKEN} \
  <docker_image> \
  --model <model_id> \
  <vllm_args> \
  --port <port>

步骤 5:向用户确认

启动前,向用户展示摘要并请其确认:

  • 模型:完整的 HuggingFace ID(例如 Qwen/Qwen3.5-122B-Instruct)
  • 精度:所用变体(例如 BF16、FP8)及原因
  • 权重显存:来自 estimate_vram.py 的结果
  • GPU:检测到的硬件和 VRAM
  • TP:张量并行度(1、2、4、8)
  • 上下文:可实现的最大上下文长度(以及是否受限)
  • 端口:端点将使用的端口

如果选择了量化替代版本(步骤 4 的适配性检查),请说明原始模型不适配, 并指出所用的替代版本。

等待用户确认后再继续。

第 6 步:启动并验证

启动前,检查端口冲突:

ss -tlnp 2>/dev/null | grep ':<port> '

如果该端口上有 Docker 容器,请使用 docker rm -f <name> 停止它。

运行 Docker 命令。然后使用此循环轮询健康状态:

while docker inspect --format='{{.State.Running}}' <container_name> 2>/dev/null | grep -q true; do
  curl -sf http://localhost:<port>/health && echo "READY" && exit 0
  sleep 60
done
echo "FAILED -- container exited"

加载期间出现 503 属于正常情况。根据模型大小(来自 hf-mem 的权重内存)选择轮询策略:

  • 小型模型(权重 < 100 GB):将轮询作为阻塞命令运行,并将 Bash 工具的 timeout 设为 600000(10 分钟)。大多数已缓存的模型会在 2-5 分钟内就绪。
  • 大型模型(权重 >= 100 GB):运行轮询时将 Bash 工具的 run_in_background 设为 true。然后使用 TaskOutput,设置 block: true 和 timeout: 600000,每次检查最多等待 10 分钟。如果任务在这之后仍在运行,请使用相同参数再次调用 TaskOutput。这样每等待 10 分钟只需消耗 1 轮,而不是每次检查都消耗一轮。后台循环会持续运行,直到容器健康或退出。

健康状态返回 200 后,发送预热请求(触发 HIP 内核编译,在 gfx942 上约需 40-45 秒):

curl -s http://localhost:<port>/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"<model_id>","messages":[{"role":"user","content":"say hi"}],"max_tokens":5}'

预热成功后,提供连接信息表,让用户可以立即调用端点:

字段值
模型<model_id>
服务模型名称<served-model-name or model_id>
基础 URLhttp://<host>:<port>/v1
API 密钥无(本地)
端口<port>
张量并行<tp>
最大上下文<context>
GPU<detected GPU>

然后提供一个可直接运行、使用上述确切值的示例:

curl -s http://<host>:<port>/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"<model_id>","messages":[{"role":"user","content":"Hello"}]}'

远程与本地

所有脚本都接受 --host user@hostname。提供该参数时,脚本会通过 SSH 连接到目标主机。设置 ROCM_SSH_HOST 和 ROCM_SSH_USER 环境变量,即可避免每次都传入 --host。

对于远程 Docker 命令,请通过 SSH 运行:

ssh user@host 'docker run -d ...'

健康检查和预热所用的 curl URL 请使用 localhost(curl 在远程主机上运行)。

注意事项

CUDA_VISIBLE_DEVICES 被设为空字符串——ROCm 会将此变量映射到 HIP_VISIBLE_DEVICES。将其设为空字符串会隐藏所有 GPU。 CUDA_VISIBLE_DEVICES=0,1 可正常用于限制 GPU(与 HIP_VISIBLE_DEVICES=0,1 相同)。如果主机上该变量为空,请取消设置: unset CUDA_VISIBLE_DEVICES。不要将 --env CUDA_VISIBLE_DEVICES=(空值) 传入 Docker——这也会隐藏容器内的所有 GPU。

gfx942(MI300X)上的 FP4BMM 崩溃——如果容器立即因段错误或非法指令退出:在 gfx942 上,VLLM_ROCM_USE_AITER_FP4BMM 必须设为 0。gfx942 的 gpu_overrides.json 中已正确设置此项。 请参阅 vLLM issue #34641。

HIP error: no kernel image——Docker 镜像中没有为你的 GPU 的 gfx 版本编译的内核。请使用 vllm/vllm-openai-rocm:latest;其中包含 gfx942 和 gfx950 内核。

MLA 模型需要 --block-size 1——DeepSeek-R1/V3、Kimi-K2.5。 否则 MLA 注意力后端会在不提示的情况下回退到较慢的路径。 这些模型的配方参数中已包含此项。

多 GPU 上的 MoE 模型需要 --distributed-executor-backend mp—— Qwen3-235B、GLM-4.5、MiniMax-M2。默认的分布式执行器在 ROCm 上无法可靠运行 MoE。

HIP 图捕获期间发生 OOM——如果容器日志在 "capturing CUDA graphs" 或 "capturing HIP graphs" 后显示 "out of memory",说明模型能装入 VRAM,但没有足够的余量用于图捕获。请在 vLLM 参数中添加 --enforce-eager 后重试。此选项会禁用图捕获并释放 1-2 GB 显存。代价是解码延迟略高,但模型可以运行。

"Engine core initialization failed"——这个含义不明确的错误表示引擎核心子进程已退出。请检查容器早期日志:docker logs <name> 2>&1 | head -50。常见原因包括:无权访问受限模型(未在 HF 上接受许可)、当前 vLLM 版本不支持该架构、加载权重时发生 OOM、自定义架构缺少 --trust-remote-code,或 vLLM 版本过旧,无法支持该模型(请检查配方中的 min_vllm_version)。

/dev/kfd 权限被拒绝——用户不属于 video 或 render 组。解决方法:sudo usermod -aG video,render $USER(需要重新登录)。

未配置 SSH 密钥——脚本使用 BatchMode=yes SSH。如果 SSH 失败并显示 Permission denied (publickey),请先配置基于密钥的访问。

在共享主机上限制 GPU——使用 --env HIP_VISIBLE_DEVICES=0,1 或 --env CUDA_VISIBLE_DEVICES=0,1,按索引指定目标 GPU。 HIP_VISIBLE_DEVICES 是 AMD 的标准变量;CUDA_VISIBLE_DEVICES 也可使用(ROCm 会将其映射)。不要将任一变量设为空字符串。


参考

精度兼容性、VRAM 估算、Docker 标志和已知问题: reference.md

评论

支持 Markdown