ROCm 从入门到精通 - 完整学习指南
本文是AMD ROCm GPU计算平台的入门指南,基于ROCm 7.2.1版本编写。主要内容包括:1) ROCm简介及其生态系统,支持AMD Instinct和Radeon GPU系列;2) 环境安装与验证方法,涵盖Linux/Docker/Windows平台;3) HIP编程基础,包括线程模型、内存管理和优化技巧;4) GPU架构与性能优化原则;5) ROCm核心库(rocBLAS/rocFFT
📅 最后更新:2026-03-30
🎯 目标:帮助你从零开始掌握 AMD ROCm GPU 计算平台
📚 版本:基于 ROCm 7.2.1(生产版本)
📖 目录
1. ROCm 简介
1.1 什么是 ROCm?
ROCm(Radeon Open Compute Platform)是 AMD 开发的开源 GPU 计算软件栈,用于高性能计算(HPC)和人工智能(AI)工作负载。
核心特点:
- 🔓 开源:完全开放源代码
- 🚀 高性能:针对 AMD Instinct 和 Radeon GPU 优化
- 🔧 多语言支持:HIP、OpenCL、OpenMP 等
- 🌐 跨平台:支持 Linux 和 Windows
1.2 ROCm 生态系统
ROCm 软件栈
├── HIP (Heterogeneous-Compute Interface for Portability)
│ ├── C++ Runtime API
│ └── Kernel 语言
├── ROCm 库
│ ├── rocBLAS(线性代数)
│ ├── rocFFT(快速傅里叶变换)
│ ├── rocRAND(随机数生成)
│ └── MIOpen(机器学习)
├── 编译器
│ ├── HIPCC(HIP 编译器)
│ └── LLVM/Clang
└── 工具
├── rocprof(性能分析)
├── rocgdb(调试器)
└── HIP Trace(跟踪工具)
1.3 支持的硬件
AMD Instinct GPU(数据中心):
- MI300X、MI300A 系列
- MI250X、MI250 系列
- MI210、MI100 系列
AMD Radeon GPU(工作站):
- Radeon RX 7000 系列
- Radeon RX 6000 系列
- Radeon PRO W 系列
AMD Ryzen APU:
- 支持 ROCm 的 Ryzen 处理器
2. 环境准备与安装
2.1 系统要求(Linux)
操作系统:
- Ubuntu 22.04.x / 24.04.x(推荐)
- RHEL 9.x
- SLES 15 SP6
硬件要求:
- x86_64 或 AMD64 处理器
- 至少 8GB RAM(推荐 16GB+)
- 支持 ROCm 的 AMD GPU
- PCIe 4.0 x16 插槽(推荐)
2.2 快速安装(Ubuntu)
# 1. 添加 ROCm 仓库密钥
wget https://repo.radeon.com/rocm/rocm.gpg.key
sudo apt-key add rocm.gpg.key
# 2. 添加 ROCm 仓库
echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/rocm.gpg] \
https://repo.radeon.com/rocm/apt/7.2.1 jammy main' | \
sudo tee /etc/apt/sources.list.d/rocm.list
# 3. 更新包列表
sudo apt update
# 4. 安装 ROCm
sudo apt install rocm
# 5. 添加用户到 video 和 render 组
sudo usermod -a -G video $USER
sudo usermod -a -G render $USER
# 6. 重启或重新登录
2.3 验证安装
# 检查 ROCm 版本
rocminfo
# 检查 GPU 设备
rocm-smi
# 编译测试程序
hipcc --version
# 运行 ROCm 示例
/opt/rocm/share/hip-samples/cmake/samples/0_Intro/simpleHyperQ/simpleHyperQ
2.4 Docker 安装(推荐)
# 拉取 ROCm Docker 镜像
docker pull rocm/pytorch:latest
# 运行容器(需要 KFD 和 DRI 设备)
docker run -it --device /dev/kfd --device /dev/dri \
--group-add video --cap-add=SYS_PTRACE \
--security-opt seccomp=unconfined \
rocm/pytorch:latest bash
# 在容器内验证
python -c "import torch; print(torch.cuda.is_available())"
2.5 Windows 安装(HIP SDK)
# 1. 下载 HIP SDK for Windows
# 访问:https://rocm.docs.amd.com/projects/install-on-windows/
# 2. 安装 Visual Studio 2019/2022
# 需要 "Desktop Development with C++" 工作负载
# 3. 安装 HIP SDK
# 运行下载的安装程序
# 4. 验证安装
hipcc --version
3. HIP 编程基础
3.1 什么是 HIP?
HIP(Heterogeneous-Compute Interface for Portability)是 AMD 开发的 GPU 编程模型,语法与 NVIDIA CUDA 高度相似,便于代码移植。
3.2 第一个 HIP 程序
// hello_world.hip
#include <hip/hip_runtime.h>
#include <stdio.h>
// GPU Kernel(在设备上执行)
__global__ void helloFromGPU() {
printf("Hello from GPU! Thread ID: %d\n", threadIdx.x);
}
int main() {
printf("Hello from CPU!\n");
// 启动 kernel:1 个 block,4 个线程
helloFromGPU<<<1, 4>>>();
// 同步等待 GPU 完成
hipDeviceSynchronize();
return 0;
}
编译和运行:
hipcc -o hello_world hello_world.hip
./hello_world
3.3 HIP 编程模型核心概念
3.3.1 线程层次结构
Grid(网格)
└── Block(块)
└── Thread(线程)
关键变量:
threadIdx.x/y/z:线程在块内的索引blockIdx.x/y/z:块在网格内的索引blockDim.x/y/z:每个块的线程数gridDim.x/y/z:网格的块数
全局线程 ID 计算:
int globalThreadId = blockIdx.x * blockDim.x + threadIdx.x;
3.3.2 内存类型
__global__ void vectorAdd(float *A, float *B, float *C, int n) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < n) {
C[i] = A[i] + B[i]; // 全局内存访问
}
}
int main() {
// 主机内存
float *h_A, *h_B, *h_C;
// 设备内存
float *d_A, *d_B, *d_C;
// 分配设备内存
hipMalloc(&d_A, n * sizeof(float));
hipMalloc(&d_B, n * sizeof(float));
hipMalloc(&d_C, n * sizeof(float));
// 主机到设备数据传输
hipMemcpy(d_A, h_A, n * sizeof(float), hipMemcpyHostToDevice);
hipMemcpy(d_B, h_B, n * sizeof(float), hipMemcpyHostToDevice);
// 启动 kernel
int threadsPerBlock = 256;
int blocksPerGrid = (n + threadsPerBlock - 1) / threadsPerBlock;
vectorAdd<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, d_C, n);
// 设备到主机数据传输
hipMemcpy(h_C, d_C, n * sizeof(float), hipMemcpyDeviceToHost);
// 释放设备内存
hipFree(d_A);
hipFree(d_B);
hipFree(d_C);
}
3.4 共享内存优化
__global__ void matrixTransposeShared(float *in, float *out, int width, int height) {
// 共享内存声明
__shared__ float tile[32][32];
int x = blockIdx.x * 32 + threadIdx.x;
int y = blockIdx.y * 32 + threadIdx.y;
// 从全局内存加载到共享内存
tile[threadIdx.y][threadIdx.x] = in[y * width + x];
// 同步块内所有线程
__syncthreads();
// 转置写入
int transX = blockIdx.y * 32 + threadIdx.x;
int transY = blockIdx.x * 32 + threadIdx.y;
out[transY * width + transX] = tile[threadIdx.x][threadIdx.y];
}
3.5 原子操作
__global__ void histogram(unsigned char *data, int *hist, int n) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < n) {
unsigned char value = data[idx];
// 原子加法,避免竞争条件
atomicAdd(&hist[value], 1);
}
}
3.6 流与异步执行
// 创建流
hipStream_t stream1, stream2;
hipStreamCreate(&stream1);
hipStreamCreate(&stream2);
// 在不同流中异步执行 kernel
kernel1<<<blocks, threads, 0, stream1>>>(...);
kernel2<<<blocks, threads, 0, stream2>>>(...);
// 流同步
hipStreamSynchronize(stream1);
hipStreamSynchronize(stream2);
// 销毁流
hipStreamDestroy(stream1);
hipStreamDestroy(stream2);
4. GPU 架构与性能优化
4.1 AMD GPU 架构概览
CDNA 架构(数据中心):
- CDNA 3(MI300 系列)
- CDNA 2(MI250 系列)
- CDNA 1(MI100 系列)
RDNA 架构(游戏/工作站):
- RDNA 3(RX 7000 系列)
- RDNA 2(RX 6000 系列)
4.2 性能优化原则
4.2.1 内存访问优化
// ❌ 低效:非合并访问
__global__ void inefficient(float *data) {
int idx = threadIdx.x * blockDim.x + threadIdx.y; // 跨步访问
float val = data[idx];
}
// ✅ 高效:合并访问
__global__ void efficient(float *data) {
int idx = blockIdx.x * blockDim.x + threadIdx.x; // 连续访问
float val = data[idx];
}
4.2.2 占用率优化
// 查询最大占用率
int minGridSize, blockSize;
hipOccupancyMaxPotentialBlockSize(&minGridSize, &blockSize,
myKernel, 0, 0);
// 使用计算出的 block 大小启动 kernel
myKernel<<<minGridSize, blockSize>>>(...);
4.2.3 指令级优化
// 使用向量化类型
float4 a, b, c;
c.x = a.x + b.x;
c.y = a.y + b.y;
c.z = a.z + b.z;
c.w = a.w + b.w;
// 或使用内置向量操作
float4 c = make_float4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
4.3 使用 rocprof 性能分析
# 基本性能分析
rocprof --hip-trace --sys-trace ./my_application
# 生成性能报告
rocprof --stats ./my_application
# 分析特定 kernel
rocprof --kernel-trace -i input.txt ./my_application
4.4 性能调优检查清单
- 确保内存访问是合并的
- 最大化共享内存使用
- 减少主机 - 设备数据传输
- 使用异步流重叠计算和传输
- 优化 block 和 grid 大小
- 避免分支发散
- 使用合适的精度(FP16/FP8 用于 AI)
5. ROCm 库与工具
5.1 rocBLAS(线性代数)
#include <rocblas/rocblas.h>
// 矩阵乘法 C = A * B
void matrixMultiply(float *A, float *B, float *C, int m, int n, int k) {
rocblas_handle handle;
rocblas_create_handle(&handle);
float alpha = 1.0f, beta = 0.0f;
rocblas_sgemm(handle,
rocblas_operation_none, rocblas_operation_none,
m, n, k,
&alpha,
A, m,
B, k,
&beta,
C, m);
rocblas_destroy_handle(handle);
}
5.2 rocFFT(快速傅里叶变换)
#include <rocfft/rocfft.h>
// 创建 FFT 计划
rocfft_plan plan;
rocfft_plan_create(&plan,
rocfft_calculation_type_complex_to_complex,
rocfft_array_type_complex_interleaved,
rocfft_array_type_complex_interleaved,
1, &length, 1, nullptr);
// 执行 FFT
rocfft_execute(plan, in_buffer, out_buffer, nullptr);
// 销毁计划
rocfft_plan_destroy(plan);
5.3 rocRAND(随机数生成)
#include <rocrand/rocrand.h>
rocrand_generator generator;
rocrand_create_generator(&generator, ROCRAND_RNG_PSEUDO_DEFAULT);
// 生成均匀分布随机数
float *randomNumbers;
hipMalloc(&randomNumbers, n * sizeof(float));
rocrand_generate_uniform(generator, randomNumbers, n);
rocrand_destroy_generator(generator);
5.4 MIOpen(机器学习)
#include <miopen/miopen.h>
// 创建卷积描述符
miopenConvolutionDescriptor_t convDesc;
miopenCreateConvolutionDescriptor(&convDesc);
// 配置卷积参数
miopenInitConvolutionDescriptor(convDesc,
miopenConvolution,
pad_h, pad_w,
stride_h, stride_w,
dilation_h, dilation_w);
// ... 执行卷积操作
5.5 开发工具
roc-gdb(调试器):
# 启动调试器
roc-gdb ./my_application
# 常用命令
(gdb) break kernel_name
(gdb) run
(gdb) info threads
(gdb) thread apply all bt
Omniperf(性能分析):
# 收集性能数据
python3 omniperf.py analyze --name my_kernel --kernel my_kernel \
--rocm-path /opt/rocm -- ./my_application
6. AI/深度学习应用
6.1 PyTorch on ROCm
安装:
# 使用 pip 安装
pip3 install torch torchvision torchaudio \
--index-url https://download.pytorch.org/whl/rocm6.0
# 或使用 Docker
docker pull rocm/pytorch:latest
验证:
import torch
print(f"PyTorch version: {torch.__version__}")
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"CUDA device count: {torch.cuda.device_count()}")
print(f"Current device: {torch.cuda.current_device()}")
print(f"Device name: {torch.cuda.get_device_name(0)}")
# 创建张量并移动到 GPU
x = torch.randn(3, 3).cuda()
y = torch.randn(3, 3).cuda()
z = x @ y # 矩阵乘法
print(z)
6.2 TensorFlow on ROCm
安装:
pip install tensorflow-rocm
验证:
import tensorflow as tf
print(f"TensorFlow version: {tf.__version__}")
print(f"GPUs available: {tf.config.list_physical_devices('GPU')}")
# 创建简单模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
6.3 vLLM 推理部署
# 安装 vLLM for ROCm
pip install vllm
# 运行模型推理
python -m vllm.entrypoints.api_server \
--model meta-llama/Llama-2-7b-chat-hf \
--port 8000 \
--tensor-parallel-size 1
6.4 AI 开发者教程资源
官方教程库: https://github.com/ROCm/gpuaidev
教程分类:
- 推理:vLLM、SGLang、Ollama 部署
- 微调:LoRA、GRPO、Unsloth
- 预训练:Megatron-LM、TorchTitan
- 优化:量化、内核开发、性能分析
7. 实战项目
7.1 项目 1:向量加法(入门)
// vector_add.hip
#include <hip/hip_runtime.h>
#include <stdio.h>
#define N 1000000
__global__ void vectorAdd(float *a, float *b, float *c) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < N) {
c[i] = a[i] + b[i];
}
}
int main() {
float *h_a, *h_b, *h_c;
float *d_a, *d_b, *d_c;
// 分配主机内存
h_a = (float*)malloc(N * sizeof(float));
h_b = (float*)malloc(N * sizeof(float));
h_c = (float*)malloc(N * sizeof(float));
// 初始化数据
for (int i = 0; i < N; i++) {
h_a[i] = i * 1.0f;
h_b[i] = i * 2.0f;
}
// 分配设备内存
hipMalloc(&d_a, N * sizeof(float));
hipMalloc(&d_b, N * sizeof(float));
hipMalloc(&d_c, N * sizeof(float));
// 复制数据到设备
hipMemcpy(d_a, h_a, N * sizeof(float), hipMemcpyHostToDevice);
hipMemcpy(d_b, h_b, N * sizeof(float), hipMemcpyHostToDevice);
// 启动 kernel
int threadsPerBlock = 256;
int blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock;
vectorAdd<<<blocksPerGrid, threadsPerBlock>>>(d_a, d_b, d_c);
// 复制结果回主机
hipMemcpy(h_c, d_c, N * sizeof(float), hipMemcpyDeviceToHost);
// 验证结果
printf("Result[0] = %f (expected: 0.0)\n", h_c[0]);
printf("Result[999] = %f (expected: 2997.0)\n", h_c[999]);
// 清理
hipFree(d_a);
hipFree(d_b);
hipFree(d_c);
free(h_a);
free(h_b);
free(h_c);
return 0;
}
7.2 项目 2:矩阵乘法(中级)
// matrix_multiply.hip
#include <hip/hip_runtime.h>
#include <stdio.h>
#define TILE_SIZE 32
__global__ void matrixMulShared(float *A, float *B, float *C, int width) {
__shared__ float As[TILE_SIZE][TILE_SIZE];
__shared__ float Bs[TILE_SIZE][TILE_SIZE];
int bx = blockIdx.x, by = blockIdx.y;
int tx = threadIdx.x, ty = threadIdx.y;
int row = by * TILE_SIZE + ty;
int col = bx * TILE_SIZE + tx;
float sum = 0.0f;
for (int t = 0; t < (width + TILE_SIZE - 1) / TILE_SIZE; t++) {
// 加载数据到共享内存
if (row < width && t * TILE_SIZE + tx < width)
As[ty][tx] = A[row * width + t * TILE_SIZE + tx];
else
As[ty][tx] = 0.0f;
if (t * TILE_SIZE + ty < width && col < width)
Bs[ty][tx] = B[(t * TILE_SIZE + ty) * width + col];
else
Bs[ty][tx] = 0.0f;
__syncthreads();
// 计算部分和
for (int k = 0; k < TILE_SIZE; k++)
sum += As[ty][k] * Bs[k][tx];
__syncthreads();
}
if (row < width && col < width)
C[row * width + col] = sum;
}
int main() {
int width = 1024;
int size = width * width * sizeof(float);
// ... 内存分配和初始化(类似向量加法)
dim3 threadsPerBlock(TILE_SIZE, TILE_SIZE);
dim3 blocksPerGrid((width + TILE_SIZE - 1) / TILE_SIZE,
(width + TILE_SIZE - 1) / TILE_SIZE);
matrixMulShared<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, d_C, width);
// ... 结果验证和清理
}
7.3 项目 3:神经网络推理(高级)
# simple_nn_inference.py
import torch
import torch.nn as nn
import time
class SimpleNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(SimpleNN, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_size, output_size)
self.softmax = nn.Softmax(dim=1)
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return self.softmax(x)
# 创建模型
model = SimpleNN(784, 256, 10)
# 移动到 GPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)
# 创建随机输入
batch_size = 32
input_data = torch.randn(batch_size, 784).to(device)
# 预热
for _ in range(10):
_ = model(input_data)
# 性能测试
torch.cuda.synchronize()
start = time.time()
for _ in range(100):
output = model(input_data)
torch.cuda.synchronize()
end = time.time()
print(f"Average inference time: {(end - start) / 100 * 1000:.2f} ms")
print(f"Throughput: {batch_size / ((end - start) / 100):.2f} samples/sec")
8. 调试与故障排除
8.1 常见错误及解决方案
错误 1:hipErrorNoDevice
原因: 未检测到 GPU 设备
解决方案:
# 检查用户组
groups $USER
# 添加用户到必要组
sudo usermod -a -G video,render $USER
# 重启或重新登录
# 验证设备
rocminfo
错误 2:hipErrorOutOfMemory
原因: GPU 显存不足
解决方案:
// 检查可用显存
size_t free, total;
hipMemGetInfo(&free, &total);
printf("Free: %zu MB, Total: %zu MB\n", free / 1024 / 1024, total / 1024 / 1024);
// 减少 batch size 或模型大小
// 使用梯度检查点
// 启用混合精度训练
错误 3:内核执行失败
原因: Kernel 配置错误或资源不足
调试方法:
// 检查 kernel 启动错误
vectorAdd<<<blocks, threads>>>(...);
hipError_t err = hipGetLastError();
if (err != hipSuccess) {
printf("Kernel launch error: %s\n", hipGetErrorString(err));
}
// 同步并检查执行错误
err = hipDeviceSynchronize();
if (err != hipSuccess) {
printf("Kernel execution error: %s\n", hipGetErrorString(err));
}
8.2 调试工具
使用 roc-gdb:
# 编译时添加调试信息
hipcc -g -G -o my_app my_app.hip
# 启动调试器
roc-gdb ./my_app
# 常用命令
(gdb) break myKernel
(gdb) run
(gdb) info threads
(gdb) thread 1
(gdb) frame
(gdb) print variable
使用 HIP Trace:
# 启用 HIP 跟踪
export HIP_TRACE=1
export HIP_TRACE_FILE=trace.log
# 运行程序
./my_app
# 分析跟踪文件
cat trace.log
8.3 性能问题排查
# 1. 使用 rocprof 分析
rocprof --stats ./my_app
# 2. 检查 GPU 利用率
rocm-smi --showuse
# 3. 监控温度
rocm-smi --showtemp
# 4. 查看显存使用
rocm-smi --showmeminfo vram
附录 A:快速参考卡
HIP vs CUDA 语法对比
| 功能 | CUDA | HIP |
|---|---|---|
| 头文件 | #include <cuda_runtime.h> |
#include <hip/hip_runtime.h> |
| 内存分配 | cudaMalloc |
hipMalloc |
| 内存复制 | cudaMemcpy |
hipMemcpy |
| 内核启动 | kernel<<<blocks, threads>>>() |
kernel<<<blocks, threads>>>() |
| 同步 | cudaDeviceSynchronize() |
hipDeviceSynchronize() |
| 错误检查 | cudaGetLastError() |
hipGetLastError() |
常用编译选项
# 基本编译
hipcc -o app app.hip
# 优化编译
hipcc -O3 -o app app.hip
# 调试编译
hipcc -g -G -o app app.hip
# 指定 GPU 架构
hipcc --amdgpu-target=gfx908,gfx90a -o app app.hip
# 显示编译命令
hipcc -v -o app app.hip
性能优化速查
✅ 合并内存访问
✅ 最大化共享内存使用
✅ 减少主机 - 设备传输
✅ 使用异步流
✅ 优化 block/grid 大小
✅ 避免分支发散
✅ 使用合适精度
❌ 随机内存访问
❌ 过度使用全局内存
❌ 频繁数据传输
❌ 同步阻塞
❌ 小 block 大小
❌ 复杂条件分支
❌ 不必要的双精度
祝你 GPU 编程之旅顺利!🚀
更多推荐


所有评论(0)