第一章:开发环境搭建——工欲善其事,必先利其器
各位同学,咱们直接进入正题。做嵌入式开发,尤其是AMD平台,环境搭建是第一道坎。我见过太多人卡在这一步,折腾一整天连个Hello World都跑不起来。今天我就把15年踩过的坑,一次性给你讲透。
1.1 安装AMD官方工具链:ROCm与AOCC
先说ROCm。这是AMD的GPU计算平台,说白了就是让CPU和GPU能好好配合干活。我刚开始接触时,总觉得这东西跟CUDA差不多,结果发现坑不少。
核心要点:ROCm目前只支持Ubuntu 20.04/22.04 LTS,别用其他发行版折腾自己。
安装步骤其实不复杂,但顺序很重要。我个人习惯这样来:
- 添加AMD官方源
wget -q -O - https://repo.radeon.com/rocm/rocm.gpg.key | sudo apt-key add - echo 'deb [arch=amd64] https://repo.radeon.com/rocm/apt/5.7.1 ubuntu main' | sudo tee /etc/apt/sources.list.d/rocm.list - 安装核心组件
sudo apt update sudo apt install rocm-dev rocm-libs rocm-dkms - 验证安装
rocminfo | grep "Name:"
嗯,这里要注意。安装完成后一定要重启,不然驱动加载不上。我曾经有一次急着演示,没重启就跑了测试程序,结果GPU死活不认,场面一度很尴尬。
再说AOCC——AMD的优化编译器。这东西比GCC快不少,尤其对Zen架构有专门优化。安装更简单:
wget https://developer.amd.com/wordpress/media/files/aocc-compiler-4.2.0.tar
tar -xf aocc-compiler-4.2.0.tar
cd aocc-compiler-4.2.0
./install.sh
我的小技巧:装完后把AOCC的bin目录加到PATH里,我一般写在~/.bashrc最后一行:export PATH=/opt/AMD/aocc-compiler-4.2.0/bin:$PATH
1.2 配置交叉编译环境
交叉编译,说白了就是在你的电脑上编译出能在目标板上跑的程序。为什么需要这个?因为嵌入式设备的性能通常不够跑编译器。
我建议用sysroot方式来管理。这样最干净,不会污染你的系统库。
具体步骤:
- 下载AMD提供的交叉编译工具链
wget https://developer.amd.com/wordpress/media/files/x86_64-amd-linux-gnu.tar.xz tar -xf x86_64-amd-linux-gnu.tar.xz -C /opt/ - 设置环境变量
export CROSS_COMPILE=/opt/x86_64-amd-linux-gnu/bin/x86_64-amd-linux-gnu- export CC=${CROSS_COMPILE}gcc export CXX=${CROSS_COMPILE}g++ - 测试编译
$CC -o hello hello.c file hello # 输出应该显示:ELF 64-bit LSB executable, x86-64, version 1 (SYSV)
避坑指南:我曾经犯过一个低级错误——忘了设置--sysroot参数。结果编译出来的程序在目标板上运行时,报了一堆"cannot find shared library"的错误。折腾了两天才发现是库路径没指对。
正确的做法是加上这个参数:
export CFLAGS="--sysroot=/opt/x86_64-amd-linux-gnu/sysroot"
1.3 搭建QEMU模拟器调试环境
QEMU这东西,说白了就是个软件模拟器。你可以在上面跑完整的AMD系统,不用真硬件。我刚开始做开发时,团队就一块开发板,大家排队用。后来我搭了QEMU环境,效率直接翻倍。
安装QEMU:
sudo apt install qemu-system-x86 qemu-utils
然后你需要一个内核镜像和根文件系统。我一般用Buildroot来生成:
git clone https://github.com/buildroot/buildroot.git
cd buildroot
make qemu_x86_64_defconfig
make
编译大概要20分钟,正好可以去喝杯咖啡。完成后你会得到:
output/images/bzImage— 内核output/images/rootfs.ext2— 根文件系统
启动QEMU的命令:
qemu-system-x86_64 \
-kernel output/images/bzImage \
-drive file=output/images/rootfs.ext2,format=raw \
-append "root=/dev/sda console=ttyS0" \
-nographic
调试模式启动:加上-s -S参数,QEMU会等待GDB连接。这样你就可以在宿主机上用GDB调试目标程序了。
我个人习惯这样调试:
# 终端1:启动QEMU并等待调试器
qemu-system-x86_64 -kernel bzImage -drive file=rootfs.ext2,format=raw -append "root=/dev/sda" -s -S
# 终端2:连接GDB
gdb-multiarch vmlinux
(gdb) target remote :1234
(gdb) break start_kernel
(gdb) continue
你看,这样就能在代码里设断点、单步执行了。比用printk打印日志高效得多。
1.4 验证环境是否正常
环境搭好了,总得跑个程序验证一下。我习惯写个简单的矩阵乘法:
// test_roc.cpp
#include <hip/hip_runtime.h>
#include <iostream>
__global__ void vec_add(float* a, float* b, float* c, int n) {
int idx = threadIdx.x + blockIdx.x * blockDim.x;
if (idx < n) c[idx] = a[idx] + b[idx];
}
int main() {
int n = 1024;
float *a, *b, *c;
hipMalloc(&a, n * sizeof(float));
hipMalloc(&b, n * sizeof(float));
hipMalloc(&c, n * sizeof(float));
vec_add<<<1, 256>>>(a, b, c, n);
hipDeviceSynchronize();
std::cout << "ROCm works!" << std::endl;
return 0;
}
用AOCC编译:
/opt/AMD/aocc-compiler-4.2.0/bin/clang++ -o test_roc test_roc.cpp -I/opt/rocm/include -L/opt/rocm/lib -lhip_hcc
检查结果:如果输出"ROCm works!",说明环境没问题。如果报错,八成是库路径没配好。检查一下LD_LIBRARY_PATH有没有包含/opt/rocm/lib。
好了,环境搭建就这些。你想想看,其实步骤不多,但每一步都有讲究。我当年刚入行时,光装ROCm就折腾了一周,现在你照着这个流程,半天应该就能搞定。
下一章我们讲调试工具的使用,到时候我会分享一些实战中遇到的奇葩问题。嗯,先到这吧,有问题随时找我。