环境初始化:权限与驱动的双重校验

拿到一台预装好 AMD Instinct GPU 的 DevCloud 实例,很多开发者习惯直接跳进 Docker 或者开始 pip install,这往往是后续“环境地狱”的根源。在 Ubuntu 22.04 LTS 环境下,ROCm 7.x 对内核的依赖非常明确,但最容易被忽视的是用户组权限。

系统安装完成后,第一件事不是装驱动,而是确认当前用户是否拥有调用 GPU 硬件的资格。ROCm 的内核驱动通过 /dev/kfd/dev/dri 设备节点暴露接口,默认情况下普通用户是无权访问的。如果跳过这一步,后续所有涉及 GPU 的计算任务都会报 Permission denied 或者静默失败。

执行以下命令将当前用户加入 videorender 组:

sudo usermod -aG video,render $USER

注意:执行完必须重启系统(sudo reboot),否则组策略不会生效。这是无数人踩过的坑,别试图用 newgrp 临时切换,重启是最稳妥的方案。

重启后,不要急着验证 PyTorch,先用原生工具链检查驱动状态。运行 rocm-smi,如果能看到清晰的显卡列表、温度、功耗以及显存使用率,说明内核态驱动工作正常。如果输出为空或报错,检查 /dev/kfd 是否存在。紧接着运行 rocminfo,重点查看输出的 Agent 信息,确认识别到的架构代码(如 gfx90a 对应 MI250X,gfx942 对应 MI300X)与你手中的硬件型号一致。这一步能提前规避 80% 因架构不匹配导致的“非法指令”错误。

源码编译:架构代码与依赖陷阱

虽然 PyTorch 提供了预编译的 ROCm 版本,但在生产环境中,为了获得针对特定架构的最佳算子性能,源码编译是必经之路。这也是整个流程中最容易“翻车”的环节。

首先创建一个干净的 Conda 环境,避免污染系统 Python。安装构建依赖时,除了常规的 ninjawheel,务必确认编译器版本。ROCm 7.x 通常对 GCC 11 或 Clang 15 支持最好,版本过高可能导致链接错误。

最关键的步骤在于设置环境变量。在编译 PyTorch 之前,必须显式指定 PYTORCH_ROCM_ARCH

export PYTORCH_ROCM_ARCH="gfx942"  # 根据 rocminfo 结果替换为你的架构代码
export MAX_JOBS=$(nproc)           # 利用多核加速编译

如果忽略这个变量,PyTorch 可能会编译成通用版本或者错误的架构版本,运行时直接崩溃且没有任何友好的错误提示,只会抛出一个神秘的 Illegal instruction

接着开始编译:

git clone --recursive https://github.com/pytorch/pytorch.git
cd pytorch
# 切换到稳定的 release 分支,例如 v2.4.0
git checkout v2.4.0 
python setup.py install

PyTorch 编译完成后,验证环节同样有讲究。在 ROCm 环境下,虽然部分接口兼容 CUDA 命名,但建议使用 torch.rocm.is_available() 或直接尝试分配张量到 cuda 设备(取决于具体版本的别名映射)来测试。

接下来是 vLLM 的编译。vLLM 强依赖 Triton 编译器,必须确保安装的 Triton 版本与当前 PyTorch 后端严格匹配,否则会出现严重的段错误。在安装 vLLM 时,同样需要传入 HIP 路径:

export HIP_PATH=/opt/rocm
pip install vllm --no-build-isolation

遇到 kernel not found 或链接报错时,大概率是缓存问题。清理 build/ 目录和 __pycache__,重新指定架构代码编译通常能解决问题。不要盲目升级依赖库,有时候回退到一个稳定的 Triton 版本比追逐最新版更有效。

显存优化与服务启动实战

环境就绪后,真正的挑战在于如何让大模型跑起来且不爆显存。vLLM 的核心优势在于 PagedAttention 技术,它将 KV Cache 的管理粒度细化到了块级别,极大地减少了显存碎片。但在 AMD 平台上,参数的微调依然关键。

启动服务时,--gpu-memory-utilization 是最敏感的参数。很多文档建议设为 0.95,但在实际生产中,我建议控制在 0.90 到 0.92 之间。ROCm 驱动本身需要一定的显存开销用于上下文切换和缓冲区,留得太少极易导致瞬时峰值触发 OOM(内存溢出),让服务直接崩溃。

针对显存碎片化,可以通过 --block-size 调整。对于长文本场景,较大的 block size(如 32 或 64)能减少管理开销;而对于短文本高并发场景,较小的 block size 利用率更高。此外,如果模型支持,开启 --quantization fp8 不仅能减半显存占用,还能显著提升推理吞吐,前提是确认当前 ROCm 版本已完整支持该量化算子。

下面是一个典型的启动命令示例,假设我们要部署一个 70B 的模型并使用双卡并行:

vllm serve /path/to/model \
    --host 0.0.0.0 \
    --port 8000 \
    --tensor-parallel-size 2 \
    --gpu-memory-utilization 0.90 \
    --block-size 16 \
    --dtype bfloat16

启动过程中,密切观察日志。当看到 “Uvicorn running on…” 且没有显存报错时,服务才算真正拉起。此时可以用 curl 发送一个简单的请求测试:

curl http://localhost:8000/v1/completions \
    -H "Content-Type: application/json" \
    -d '{"model": "your-model", "prompt": "Hello", "max_tokens": 10}'

如果返回流畅且延迟在预期范围内,恭喜你已经跨过了最难的门槛。后续只需结合 benchmark_serving.py 进行压力测试,根据 RPS 和 TTFT 指标微调 --max-num-seqs 即可。从权限配置到源码编译,再到显存调优,这套流程虽然繁琐,但一旦跑通,AMD 平台的高性价比优势便能真正转化为生产力。

200小时GPU算力已就位,快来领取:https://marketing.csdn.net/questions/Q2604140858304426315?utm_source=AIpaper

文章海报

Logo

免费领 200 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐