为什么选择 AMD 显卡做微调?

提到大模型微调,很多人的第一反应就是“显存不够”或者“必须上 NVIDIA"。对于预算有限的研究人员和学生党来说,昂贵的 A100/H100 确实让人望而却步。但实际上,AMD 的 Instinct 系列甚至部分高端消费级显卡,在 ROCm 生态日益成熟的今天,已经完全具备了低成本跑通大模型的能力。

最近我手头正好有一张闲置的 AMD 显卡,想着能不能用它来试试 LoRA 微调。目标很明确:不追求极致的分布式训练,只验证单卡环境下,利用 LLaMA-Factory 能否稳定收敛,以及成本到底能压到多低。经过几天的折腾和参数调优,我不仅成功跑通了流程,还解决了一个棘手的梯度爆炸问题。这篇文章就记录下具体的配置细节和踩坑经验,希望能给想尝试“贫民窟”微调方案的朋友一些参考。

环境准备与核心配置修改

工欲善其事,必先利其器。在 AMD 平台上跑大模型,核心在于让 PyTorch 正确识别 ROCm 后端,而不是去查找不存在的 CUDA 库。我使用的工具链是 LLaMA-Factory,它对 ROCm 的支持已经相当友好,但默认的配置文件往往还是针对 NVIDIA 环境预设的,直接运行通常会报错或无法调用 GPU。

首先,确保你的系统已经安装了正确版本的 ROCm 驱动(建议 6.0 以上),并且通过 pip 安装了支持 ROCm 的 PyTorch 版本。这一步至关重要,千万不要混用 CUDA 版的 wheel 包。

接下来是重头戏:修改 LLaMA-Factory 的配置文件。在项目目录的 examples/train_lora 文件夹下,我复制了一份新的配置文件 lora_single_amd.yaml。关键的修改点主要有两个:

  1. 指定计算类型与后端
    AMD 的 MI300 系列及部分新架构对 bf16(Brain Floating Point)支持良好,这能显著节省显存。在配置文件中,我将 compute_type 明确设置为 bf16。同时,虽然 LLaMA-Factory 会自动检测,但为了稳妥,我在启动命令中通过环境变量显式指定了设备映射:

    export HIP_VISIBLE_DEVICES=0
    

    这比 NVIDIA 的 CUDA_VISIBLE_DEVICES 更容易被忽略,导致程序默认跑到 CPU 上慢速运行。

  2. 开启 ZeRO-3 优化
    单卡显存毕竟有限,要微调 7B 甚至更大的模型,必须启用 DeepSpeed 的 ZeRO-3 策略。在配置文件中加入以下段落:

    deepspeed: examples/deepspeed/zero3.json
    

    这里需要注意,zero3.json 中的 offload_paramoffload_optimizer 建议开启并指向 cpu,这样可以将部分模型参数和优化器状态卸载到内存中,换取宝贵的显存空间来存放激活值。在我的测试中,开启 ZeRO-3 后,单卡显存占用降低了约 40%,使得微调 13B 模型成为可能。

遭遇梯度爆炸与混合精度调整

配置改好后,满怀期待地启动了训练脚本。然而,现实给了我一记重锤:训练刚开始不到 50 步,Loss 直接飙升到 NaN,随后程序报错终止。查看日志,典型的梯度爆炸(Gradient Explosion)迹象。

起初我怀疑是学习率设置过高,于是将 learning_rate2e-4 降到了 1e-5,但问题依旧。经过反复排查和社区资料比对,问题出在混合精度训练(AMP)的缩放策略上。

在 NVIDIA 平台上,AMP 的 Loss Scaler 通常能很好地处理动态缩放。但在 AMD 的 ROCm 实现中,某些算子在 bf16 精度下的数值稳定性与 CUDA 存在细微差异,特别是在 Attention 层的反向传播过程中,极易出现溢出。

解决方案如下:

我尝试了两种调整策略,最终选择了第二种作为生产环境的推荐方案:

  • 策略一:调整缩放因子。在配置文件中手动指定 loss_scale 为固定值,而不是动态调整。但这治标不治本,换个数据集可能又失效。
  • 策略二:切换纯 BF16 或关闭 AMP 特定优化。我发现 LLaMA-Factory 底层调用 DeepSpeed 时,可以通过参数强制禁用某些激进的梯度裁剪策略。更彻底的方法是,在 deepspeed 配置文件中,将 fp16bf16 模块的 loss_scale_window 调大,或者直接在使用 bf16 时,确保模型本身支持原生 bf16 运算而不依赖额外的 AMP 包装。

在我的实践中,最有效的改动是在启动参数中加入:

--disable_torch_compile

并且在 zero3.json 中确认 gradient_clipping 设置为 1.0。更重要的是,我将数据类型严格锁定为 bf16,不再让框架自动回退到 fp16。经过这番调整,Loss 曲线终于不再“起飞”,而是开始平稳下降。

训练效果验证与结论

修复了梯度爆炸问题后,训练进入了正轨。我使用了一个标准的指令微调数据集,对 Llama-3-8B 模型进行了 LoRA 微调。整个过程持续了约 4 个小时,单卡显存占用稳定在 20GB 左右(未开启 offload 时更高,开启后降至 16GB 以内)。

[外链图片转存中…(img-21335cOA-1782211491776)]
(注:此处为示意图,实际训练中 Loss 从 2.5 平滑下降至 0.8,无剧烈震荡)

从损失曲线来看,下降趋势非常平滑,没有出现异常的尖峰或停滞。在验证集上的表现也符合预期,模型能够准确遵循指令格式,回答质量与在 NVIDIA 平台上微调的结果几乎没有肉眼可见的差别。

这次实践最大的收获是打破了“非 N 卡不可”的迷信。对于学生和个人研究者来说,AMD 显卡配合 LLaMA-Factory 和 ROCm 生态,完全是一条可行的高性价比路径。关键在于细致的配置调整:

  • 务必使用原生支持 ROCm 的 PyTorch 版本。
  • 善用 ZeRO-3 和 CPU Offload 突破显存限制。
  • 遇到梯度爆炸时,优先检查混合精度策略和数据类型设置,必要时锁定 bf16 并调整梯度裁剪。

硬件只是载体,算法和工程优化才是核心。随着开源社区对 AMD 支持的不断深化,未来的微调门槛只会越来越低。如果你手头也有闲置的 AMD 显卡,不妨动手试试,说不定能省下一大笔算力开销。

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

Logo

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

更多推荐