环境筑基:从驱动验证到框架适配

在 AMD Instinct GPU 上跑通大模型微调,最大的拦路虎往往不是算法本身,而是“环境地狱”。很多开发者习惯了 NVIDIA 的 CUDA 生态,转到 ROCm 平台时容易在驱动版本和编译器匹配上栽跟头。我的实战经验是:不要盲目追新,稳定压倒一切

首先,操作系统建议选择 Ubuntu 22.04 LTS,这是目前 ROCm 7.x 支持最成熟的版本。安装完官方驱动后,别急着装 Python 包,先运行 rocm-smi 看看显卡状态。如果能看到清晰的温度、功耗和显存占用信息,说明内核态驱动工作正常。接着用 rocminfo 确认硬件架构代码(如 gfx90agfx942),这一步至关重要,后续编译 PyTorch 时必须用到这个代码,填错了会导致运行时直接报 “illegal instruction”。

接下来是重头戏:安装适配 ROCm 的 PyTorch 和 LLaMA-Factory。虽然官方提供了预编译包,但在生产级微调任务中,为了获得最佳算子性能,我强烈建议从源码编译 PyTorch。核心在于设置环境变量:

export PYTORCH_ROCM_ARCH="gfx90a"  # 替换为你实际的架构代码
export MAX_JOBS=8  # 利用多核加速编译
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm7.0

安装完 PyTorch 后,再克隆 LLaMA-Factory 仓库。注意,LLaMA-Factory 底层依赖 DeepSpeed 或 FSDP,在 AMD 平台上,我们需要确保它们能正确识别 HIP 后端。如果遇到 import deepspeed 报错,通常需要重新编译 deepspeed 并指定 DS_BUILD_OPS=1,让它针对当前架构生成优化算子。

分布式训练配置:DeepSpeed 与 FSDP 的抉择

单卡微调小参数模型尚可,一旦涉及 7B 以上模型或多卡集群,分布式策略就成了成败关键。在 Instinct GPU 上,我主要测试了 DeepSpeed ZeRO-3 和 PyTorch 原生 FSDP 两种方案。

DeepSpeed 配置实战
DeepSpeed 在显存优化上表现激进,适合显存紧张的场景。在 ds_config.json 中,有几个针对 ROCm 的关键参数必须调优:

{
  "bf16": {
    "enabled": true
  },
  "zero_optimization": {
    "stage": 3,
    "offload_optimizer": {
      "device": "cpu",
      "pin_memory": true
    },
    "overlap_comm": true,
    "contiguous_gradients": true
  },
  "train_micro_batch_size_per_gpu": 2,
  "gradient_accumulation_steps": 4
}

这里开启了 BF16 混合精度,Instinct MI300 系列对 BF16 支持非常好,能大幅减少显存占用并提升计算吞吐。stage: 3 会将模型参数分片存储,极大降低单卡压力。如果显存依然吃紧,可以开启 offload_optimizer 将优化器状态卸载到 CPU,虽然会牺牲一点速度,但能保住不 OOM(显存溢出)。

FSDP 的轻量化选择
如果你不想引入 DeepSpeed 这么重的依赖,LLaMA-Factory 也支持原生 FSDP。在启动命令中加上 --fsdp "full_shard auto_wrap" 即可。FSDP 的优势在于与 PyTorch 集成度更高,调试相对简单。但在多卡通信效率上,实测发现 DeepSpeed 在 RCCL(ROCm 版的 NCCL)的调度上略胜一筹,特别是在长序列训练时,DeepSpeed 的梯度累积策略更能掩盖通信延迟。

无论选哪种,梯度检查点(Gradient Checkpointing) 都是必选项。在 LLaMA-Factory 的配置文件中启用 --gradient_checkpointing true,它能以计算换空间,将显存占用降低 60% 以上,让我们能在单卡上微调更大的上下文长度。

避坑指南:常见报错与显存调优

实战过程中,报错是常态。以下是我在 AMD 平台上遇到的几个典型问题及解决方案:

  1. RCCL 通信超时
    在多卡训练初期,经常遇到 RuntimeError: NCCL error ... timed out。这通常是因为卡间通信走错了网卡,或者防火墙阻挡。解决方法是明确指定网络接口:

    export NCCL_SOCKET_IFNAME=eth0  # 替换为你的实际内网网卡名
    export NCCL_DEBUG=INFO
    

    同时,确保所有 GPU 都在同一 PCIe 根复合体下,或者通过 Infinity Fabric 互联,避免跨 Socket 通信带来的高延迟。

  2. 显存碎片化导致 OOM
    即使总显存够用,有时也会因为碎片化导致分配失败。除了调整 per_device_train_batch_size,还可以尝试设置 PYTORCH_HIP_ALLOC_CONF=max_split_size_mb:512,限制内存块的最大分割尺寸,减少碎片产生。另外,监控显存时不要只看总量,要关注 KV Cache 和激活值的动态变化,适当减小 --cutoff_len(截断长度)也能立竿见影。

  3. 算子不支持报错
    某些自定义算子在 ROCm 下可能缺失。如果遇到 kernel not found,检查是否安装了最新版的 hipblaslt 库。必要时,可以在 LLaMA-Factory 中强制使用纯 Python 实现 fallback,虽然慢点,但能保证跑通。

效果评估与稳定性验证

经过数小时的训练,模型终于收敛。如何验证微调效果?我直接使用 LLaMA-Factory 内置的评估脚本,在验证集上测试 perplexity(困惑度)。结果显示,AMD 平台训练出的模型精度与 NVIDIA 平台基本一致,误差仅在浮点数舍入范围内,证明了 ROCm 数值计算的可靠性。

更让我惊喜的是稳定性。在连续 48 小时的多卡压力测试中,Instinct GPU 的温度和功耗始终保持在安全区间,没有出现掉卡或显存泄漏现象。通过 Prometheus + Grafana 监控面板,可以看到显存利用率曲线平滑,没有异常的尖峰波动。

总的来说,虽然 ROCm 生态的文档丰富度不如 CUDA,但只要理清驱动、编译器和分布式框架的依赖关系,LLaMA-Factory 在 AMD 显卡上的微调流程已经非常顺畅。对于追求性价比和自主可控的团队来说,这是一条值得投入的技术路线。

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

文章海报

Logo

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

更多推荐