从“跑通推理”到“动手训练”:我的 AMD ROCm 微调破冰之旅

之前我在 AMD Instinct GPU 上跑通 vLLM 推理服务时,心里其实挺打鼓的。看着社区里铺天盖地的 NVIDIA 微调教程,总下意识觉得训练这块是“绿厂”的专属领地,AMD 只能做个安静的推理节点。直到最近项目急需定制垂直领域模型,预算又卡得死死的,我才硬着头皮决定:在 ROCm 环境下,用 LLaMA-Factory 把微调这条路走通。

这一趟下来,踩坑不少,但结论很明确:AMD 不仅能训,而且生态成熟度远超想象。今天就不按教科书罗列参数了,直接复盘我这次从环境搭建到成功启动训练的真实过程,特别是那些让新手容易劝退的报错和解决思路。

第一步:别急着装包,先给系统“验明正身”

刚开始我也犯了急,直接 pip install torch,结果各种报错。后来才明白,在 AMD 平台上搞训练,环境基石比推理要严苛得多。推理只是加载权重前向传播,而训练涉及大量的梯度计算和显存动态分配,对底层驱动稳定性要求极高。

我首先检查了操作系统内核与 ROCm 驱动的匹配情况(我当时用的是 ROCm 6.2 稳定版,追求新特性的朋友可以关注 7.x 的动态,但生产环境建议求稳)。有个特别容易被忽视的细节:用户组权限

如果你发现代码能跑但识别不到卡,或者报权限错误,大概率是用户没加进组里。执行以下命令把自己加入 videorender 组:

sudo usermod -aG video $USER
sudo usermod -aG render $USER
# 记得注销重新登录生效

重启后,先用 rocm-smi 看看卡的状态。如果所有加速卡都显示正常且没有报错,这才是真正的“起跑线”。对于训练任务,我强烈建议源码编译 PyTorch,而不是直接用预编译包。虽然多花半小时,但能针对你的 GPU 架构(比如 gfx90a 或 gfx942)做指令集优化,避免运行时出现莫名其妙的“非法指令”错误。

验证后端是否真正识别成功,别光看版本号,跑这段小代码最实在:

import torch

print(f"ROCm 可用状态:{torch.cuda.is_available()}")
if torch.cuda.is_available():
    print(f"当前设备:{torch.cuda.get_device_name(0)}")
    # 简单做个矩阵乘法测试后端连通性
    x = torch.rand(5, 3).cuda()
    y = torch.rand(3, 5).cuda()
    z = torch.mm(x, y)
    print("后端计算测试通过!")
else:
    print("后端未识别,请检查驱动及环境变量 HIP_PATH")

看到 True 和计算通过,心里这块石头才算落地。

第二步:flash-attn 的“补丁”攻坚战

安装 LLaMA-Factory 本身不难,难的是它的依赖项——flash-attn。在 NVIDIA 环境下这是一键安装的,但在 AMD 上,直接 pip install flash-attn 几乎必挂,因为官方默认不支持 HIP 后端。

这是我遇到的第一个大坑。编译报错信息一堆,核心意思是找不到对应的 CUDA 算子。这时候千万别慌着换硬件,解决方案在社区里其实很成熟:

  1. 设置环境变量:限制并行编译数,防止内存爆掉。
    export MAX_JOBS=4
    export HIP_PATH=/opt/rocm
    
  2. 寻找适配分支:不要死磕主分支。我去 GitHub 上搜了 flash-attn rocm,找到了几个维护活跃的 Fork 版本(通常带有 hipify 补丁)。
  3. 本地编译安装
    # 克隆适配后的仓库(具体地址需根据当时社区最新推荐)
    git clone https://github.com/ROCm/flash-attention.git
    cd flash-attention
    pip install . --no-build-isolation
    

这一步最关键的是 --no-build-isolation,它能让你本地的 ROCm 工具链生效。如果还报错,检查 hip-dev 是否安装完整。搞定这个,LLaMA-Factory 的其他依赖(如 DeepSpeed)基本就能顺藤摸瓜装好了。记得安装时带上 deepspeed 选项:pip install -e ".[deepspeed]"

第三步:配置文件的“因地制宜”

环境搭好,接下来是数据与配置。我把业务数据清洗成了标准的 JSONL 格式(包含 instruction, input, output),这部分和 N 卡没区别。真正的差异在 .yaml 配置文件里。

打开 examples/train_lora/llama3_lora_sft.yaml,有几个地方我做了针对性修改:

  • device_map:在 ROCm 下通常设为 auto 即可,框架会自动识别。但如果多卡负载不均,可能需要手动干预。
  • finetuning_type:鉴于显存限制,我先试了 lora
  • bf16:这是重点!AMD 的 Instinct MI300X 等新架构对 bf16 支持极好。虽然参数名还叫 bf16,但底层调用的是 AMD 的 Matrix Core。开启后,吞吐量提升明显,且精度损失可控。

这里有个心得:LoRA 和 QLoRA 怎么选?
我在单张 MI250 上测试,LoRA 跑 7B 模型非常稳,显存占用约 16GB,速度快且兼容性最好。如果想挑战 70B 大模型,就得上 QLoRA(4-bit 量化),显存能压到 8GB 左右。但要注意,bitsandbytes 在 ROCm 上的支持还在完善中,如果遇到量化算子报错,要么找 bitsandbytes-rocm 分支,要么老实回退到 LoRA。对于大多数垂直领域微调,LoRA 的性价比其实更高。

第四步:启动训练与避坑指南

一切就绪,启动命令很简单:

llamafactory-cli train examples/train_lora/llama3_lora_sft.yaml

如果是多卡环境,加上 --deepspeed 参数开启 ZeRO 优化,能实现近乎线性的加速比。但在实际跑的过程中,我还是遇到了 Loss 震荡的问题。排查后发现,某些激进的算子融合选项在特定 ROCm 版本下不太稳定。我在配置里加了 --disable_flash_attn 临时排查,确认是注意力机制数值问题后,调整了学习率(从 1e-4 降到 5e-5)并配合 cosine 调度器,曲线立马平滑了。

监控方面,既然没有 nvidia-smi,我们就用 rocm-smi 或者配一套 Prometheus + DCGM exporter。盯着显存利用率看,如果发现某张卡爆显存而其他卡空闲,大概率是 DeepSpeed 的 ZeRO 级别没设对(建议直接上 ZeRO-3)。

写在最后

当看到训练日志里 Loss 稳步下降,最后成功合并权重并用 vLLM 加载起这个专属模型时,那种成就感是不言而喻的。从数据清洗到模型产出,整套流程在 AMD 生态里已经完全闭环。

这次实践最大的收获就是打破了"AMD 只能推理”的刻板印象。只要肯花点时间解决编译和算子兼容的小问题,ROCm 提供的算力性价比是非常香的。对于想低成本构建垂直领域模型的开发者来说,AMD Instinct GPU 绝对是一个值得认真考虑的选项。别再犹豫了,环境搭起来,跑通第一次训练,你会发现新世界的大门已经打开。

200小时GPU算力已就位,快来领取:https://marketing.csdn.net/questions/Q2604140858304426315?utm_source=AIpaper
在这里插入图片描述

Logo

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

更多推荐