3.1 Gem5-GPU环境搭建
核心内容:
-
✅ 系统要求
- Ubuntu 20.04/22.04
- CUDA Toolkit 11.x(注意版本兼容性)
- 至少16GB RAM
- 100GB+ 磁盘空间
-
✅ 源码获取
Gem5-GPU是Gem5的分支
git clone https://github.com/gem5/gem5-gpu.git
cd gem5-gpu或者使用子模块方式
cd gem5
git submodule update --init --recursive
依赖安装
# 基础Gem5依赖(见2.1节)
# 额外的GPU依赖
sudo apt install libboost-filesystem-dev libboost-system-dev
# CUDA Toolkit(必须11.x版本)
wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run
sudo sh cuda_11.8.0_520.61.05_linux.run
编译构建
# 编译GPU版本
cd gem5-gpu
scons build/GPU/gem5.opt -j$(nproc)
# 验证编译
./build/GPU/gem5.opt --version
- 版本兼容性
- Gem5-GPU与特定版本的Gem5对应
- 检查README中的版本要求
- 可能需要回退到特定的commit
学习资料:
- 🌐 官方GitHub :https://github.com/gem5/gem5-gpu
- 📚 安装文档 :https://gem5.org/documentation/gem5_gpu/
- 📄 论文:"gem5-GPU: A Heterogeneous CPU-GPU Simulator" (ISPASS 2012)
常见问题:
- CUDA版本不兼容:降级到CUDA 11.x
- 编译错误:检查GCC版本(建议9.x)
- 内存不足:增加交换空间或减少并行编译数
3.2 架构集成机制
核心内容:
- ✅ Gem5与GPGPU-Sim集成原理
- Gem5负责CPU和系统级仿真
- GPGPU-Sim负责GPU核心仿真
- 通过CudaGPU控制器进行通信
- ✅ CudaGPU控制器(核心组件)⭐⭐⭐⭐⭐
- 拦截CUDA API调用
- 管理GPU内存
- 调度GPU内核执行
- ✅ CUDA系统调用仿真层
- 仿真CUDA运行时API
- 处理设备内存分配
- 管理流和事件
- ✅ 内存系统集成(Ruby)
- CPU-GPU共享内存
- 一致性协议支持
- 内存映射管理
- ✅ 一致性协议机制
- VI_hammer:基于目录的一致性
- MOESI_hammer:扩展的MESI协议
架构图:
┌─────────────────────────────────────────────────┐
│ Application │
│ (CUDA Program) │
└──────────────────┬──────────────────────────────┘
│
┌──────────────────▼──────────────────────────────┐
│ CUDA Runtime API │
│ (cudaMalloc, cudaMemcpy, etc.) │
└──────────────────┬──────────────────────────────┘
│
┌──────────────────▼──────────────────────────────┐
│ CudaGPU Controller │
│ (Intercepts CUDA calls, manages GPU) │
├──────────────────────────────────────────────────┤
│ ├── Memory Management │
│ ├── Kernel Launch │
│ └── Synchronization │
└──────────────────┬──────────────────────────────┘
│
┌──────────────┴──────────────┐
│ │
┌───▼────┐ ┌────▼────┐
│ Gem5 │ │ GPGPU- │
│ (CPU) │◄───Ruby Memory──►│ Sim │
│ │ System (GPU) │ (GPU) │
└────────┘ └─────────┘
源码阅读重点
# CudaGPU控制器(核心文件)
src/gpu/gpgpu-sim/cuda_gpu.cc # 主控制器实现
src/gpu/gpgpu-sim/cuda_gpu.hh # 头文件
src/gpu/gpgpu-sim/gpgpu_sim.cc # GPGPU-Sim集成
src/gpu/gpgpu-sim/gpgpu_sim.hh
# 内存系统集成
src/mem/ruby/ # Ruby内存系统
src/mem/ruby/structures/ # 一致性协议
# 配置脚本
configs/gpu_protocol/ # GPU协议配置
configs/example/gpu_ruby.py # GPU Ruby示例
关键数据结构
// CudaGPU类(简化版)
class CudaGPU : public SimObject {
private:
GPGPUSim* gpu_sim; // GPGPU-Sim实例
RubySystem* ruby_system; // Ruby内存系统
std::vector<GPUCudaDevice*> devices; // GPU设备列表
public:
void launchKernel(KernelInfo* info); // 启动内核
void allocateMemory(size_t size); // 分配内存
void copyMemory(void* src, void* dst, size_t size); // 内存拷贝
};
学习资料:
- 📚 源码注释:阅读关键文件的注释
- 📄 论文:"GPGPU-Sim: A GPGPU Simulator" (IEEE CAL 2009)
- 📺 视频:Gem5 Bootcamp GPU专题
3.3 配置与运行
核心内容:
- ✅ GPU系统配置脚本
- CPU-GPU拓扑结构
- 内存层次配置
- 一致性协议选择
- ✅ 一致性协议配置
- VI_hammer:适合大规模系统
- MOESI_hammer:适合小规模系统
- ✅ GPU参数调优
- SM数量
- Warp大小
- 共享内存大小
- 寄存器文件大小
GPU配置示例:
# gpu_config.py
import m5
from m5.objects import *
from gem5.runtime import get_runtime_isa
# 创建系统
system = System()
system.clk_domain = SrcClockDomain(clock='1GHz', voltage_domain=VoltageDomain())
system.mem_mode = 'timing'
system.mem_ranges = [AddrRange('4GB')]
# CPU配置
system.cpu = TimingSimpleCPU()
# GPU配置(关键部分)
system.gpu = CudaGPU()
system.gpu.cpu = system.cpu
system.gpu.gpu_memory_port = system.membus.cpu_side_ports
# Ruby内存系统(GPU必需)
system.ruby = RubySystem()
system.ruby.clk_domain = SrcClockDomain(clock='1GHz', voltage_domain=VoltageDomain())
system.ruby.mem_ranges = system.mem_ranges
# 创建CPU和GPU的缓存层次
system.cpu.addPrivateSplitL1Caches(L1ICache(), L1DCache())
system.cpu.createInterruptController()
# GPU缓存配置
system.gpu.addL1Cache(L1Cache(size='64kB'))
system.gpu.addL2Cache(L2Cache(size='256kB'))
# 内存控制器
system.mem_ctrl = MemCtrl()
system.mem_ctrl.dram = DDR4_2400_8x8()
system.mem_ctrl.dram.range = system.mem_ranges[0]
# SE模式设置
process = Process()
process.cmd = ['path/to/cuda_program']
system.cpu.workload = process
system.cpu.createThreads()
# 实例化和运行
root = Root(full_system=False, system=system)
m5.instantiate()
print("Beginning GPU simulation!")
exit_event = m5.simulate()
print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}")
运行CUDA程序:
# 编译CUDA程序(使用nvcc)
nvcc -o my_cuda_program my_cuda_program.cu
# 在Gem5中运行
./build/GPU/gem5.opt configs/example/gpu_ruby.py \
--cmd=./my_cuda_program \
--mem-size=4GB \
--num-cpus=1 \
--num-gpus=1
实践项目:
- ✅ 运行Hello World CUDA程序
- ✅ 运行Rodinia基准测试中的简单程序(如backprop)
- ✅ 修改GPU SM数量观察性能变化
- ✅ 对比不同一致性协议的性能
性能监控:
# 查看模拟统计信息
cat m5out/stats.txt | grep -i gpu
# 查看GPU特定统计
cat m5out/gpu_stats.txt
# 实时监控
tail -f m5out/simout
学习资料:
- 📚 官方GPU文档 :https://gem5.org/documentation/gem5_gpu/
- 📖 配置示例 :
configs/example/gpu_ruby.py - 📺 视频教程:Gem5 GPU Tutorial系列