Skip to content

ROCm 与 AMD GPU 训练生态:从移植到调优 ​

说明:本篇为综述/无第一手实验数据,采用公开文档与迁移实践路线。

实验目标 ​

AMD GPU 在超算 Top500 的占比举足轻重(Frontier 蝉联多年榜首),训练生态(ROCm)也在快速成熟。但"CUDA 代码能不能直接跑 AMD 卡"仍是被问最多的问题。本篇目标:拆解 ROCm 软件栈的层次、HIP 移植的真实成本(哪些代码能自动转、哪些要手改)、PyTorch ROCm 版本的正确用法、以及性能调优与 CUDA 的对应关系。读完能回答:这个 CUDA 项目迁到 AMD 卡,要改多少、预期性能差距多少、先调什么。

代码逐段拆解 ​

第一段:HIP 移植——CUDA 代码的"半自动翻译" ​

cpp
// CUDA 原版(示例)
__global__ void saxpy(float *y, float a, float *x, int n) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < n) y[i] = a * x[i] + y[i];
}

// HIP 版:几乎逐行相同(hipify 工具可自动转换)
__global__ void saxpy(float *y, float a, float *x, int n) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < n) y[i] = a * x[i] + y[i];
}

// 自动转换:hipify-perl / hipify-clang
hipify-perl saxpy.cu > saxpy_hip.cpp

要点:

  1. 核心 CUDA 语法在 HIP 中 1:1 对应:__global__/blockIdx/threadIdx/__syncthreads 完全同名——HIP 的设计目标就是"CUDA 方言的超集",简单内核几乎零成本迁移。
  2. API 层有映射表:cudaMalloc→hipMalloc、cudaMemcpy→hipMemcpy、cudaStreamCreate→hipStreamCreate,hipify 工具按表自动替换——纯 CUDA API + 内核的代码,迁移成本以小时计。
  3. 真正要手改的是"库依赖":cuBLAS→rocBLAS、cuDNN→MIOpen、NCCL→RCCL、TensorRT→ROCm 推理栈——深度学习项目里这些库调用才是迁移大头,不是内核语法。

第二段:PyTorch ROCm 的正确姿势 ​

bash
# 方式 1(推荐):官方预编译 wheel
pip install torch --index-url https://download.pytorch.org/whl/rocm6.2

# 方式 2:源码构建(需与驱动/ROCm 版本严格匹配)
# 环境变量关键项
export ROCM_PATH=/opt/rocm
export HCC_AMDGPU_TARGET=gfx90a        # 对应 MI250X;gfx942 对应 MI300X

要点:

  • 预编译 wheel 是首选:PyTorch 官方发布 ROCm 版 wheel(rocm5.x/6.x),和 CUDA 版用法完全一样(torch.cuda 在 ROCm 下映射到 ROCm 后端)——纯 PyTorch 项目(无自定义 CUDA 扩展)迁移到 AMD 卡,改的只是安装源。
  • HCC_AMDGPU_TARGET 决定 kernel 生成目标:gfx90a(MI200 系列)/gfx942(MI300 系列)不能混用,编错 target 会得到"能装不能跑"的二进制。
  • 自定义 CUDA 扩展是分水岭:有 .cu 扩展要先 hipify 再重编,且依赖的 CUDA 库(cuDNN/cuBLAS)要换 ROCm 等价物——这一步决定迁移是"小时级"还是"周级"。

原理讲解 ​

ROCm 软件栈分层 ​

PyTorch/TensorFlow (ROCm 版)
  → HIP 运行时(HIP 相当于 ROCm 的 "CUDA")
  → 库层:rocBLAS(矩阵) / MIOpen(卷积) / RCCL(集合通信) / rocSOLVER
  → 编译器:HIP-Clang(LLVM 基)
  → 驱动:amdgpu + ROCm 内核模块
  → AMD GPU(gfx 系列架构)

与 CUDA 栈逐层对应:CUDA runtime→HIP runtime、cuBLAS→rocBLAS、cuDNN→MIOpen、NCCL→RCCL、nvcc→hipcc(HIP-Clang)。理解了这层映射,迁移时的"找哪个库替代"就一目了然。

性能差距在哪(与 CUDA 的诚实对比) ​

环节现状(估算口径)说明
标准算子(GEMM/conv)90%-105%rocBLAS/MIOpen 已对齐,个别算子有差距
融合/自定义算子70%-95%社区 kernel 数量与质量仍在追赶
集合通信(大规模)85%-100%RCCL 成熟度快速提升,大集群仍需验证
生态工具(profiler/调试)60%-90%rocprof/Omnitrace 可用但比 Nsight 生态少

关键认知:AMD 卡单算子性能已经不错,差距集中在生态深度(算子覆盖、调优工具、库版本节奏)而不是硬件峰值——所以"能跑多快"更多取决于项目用了多少深度 CUDA 特性。

调优对应关系 ​

CUDA 调优三板斧在 ROCm 都有对应:rocprof(≈nsys/ncu 的角色,内核耗时与硬件计数器)、HSA_XNACK 等环境变量(≈CUDA 环境变量调优)、MIOpen 的 tuner(自动选择卷积实现)。从 CUDA 迁过来的团队,先跑 rocprof 确认算子覆盖与瓶颈,再按 08 章 Nsight 的方法论套用——方法论通用,工具换名。

实验结果 ​

(估算口径,非实测;典型迁移案例)

项目类型迁移工作量端到端性能(相对同档 CUDA)
纯 PyTorch(官方 ROCm wheel)小时级90%-105%
PyTorch + 少量自定义 kernel天级85%-100%
深度 CUDA 库依赖项目周级70%-95%

工程启示 ​

  1. 先评估"库依赖深度"再定迁移工期:纯 API/内核代码自动转,库依赖(cuDNN/NCCL 等)才是工作量主体——迁移前先列依赖清单。
  2. 官方 wheel 优先,源码构建其次:wheel 和驱动/ROCm 版本匹配,省去大量编译坑;只有需要定制算子/内核优化才源码构建。
  3. 性能验收按算子拆:端到端对比之外,用 rocprof 按算子层对比(呼应 08 章剖析法),知道差距在"库覆盖"还是"kernel 质量",分别对应不同修法。
  4. 与异构调度共存:07 章讲混布调度,本篇讲 AMD 单侧——混布集群里 AMD 卡跑 ROCm 任务、NVIDIA 卡跑 CUDA 任务,调度器按架构分区(SLURM 分区/GRES 已有)。

下一篇预告:训练侧生态补完 AMD 后,回到推理侧运营——"推理服务容量规划:从 QPS 到 GPU 实例数"。

AI-HPC 智算超算专家 · Contact: openaihpc@gmail.com