本项目记录了我的cuda学习经历,和大多数人一样,通过优化矩阵乘法的过程来了解一些基本的概念。
其中Fermi架构是Compute Capability 2.0的架构。从白皮书里能了解到硬件相关的一些基本概念。比如streaming multiprocessor,有时候也简称multiprocessor或者SM。一个SM里有32个cuda core,有两个warp调度器。一个warp是由32个thread组成。和硬件结合后就比较容易理解,为什么一个block里最好至少放64个thread,因为有两个warp scheduler存在,至少可以放两个warp的thread进行工作。
Programming Guide里比较详细地介绍了编程模型(Programming Model),也比较详细地介绍了一些Runtime API。CUDA也提供了更底层的Driver API,但一般Runtime API已经够用了,而且使用起来更容易。除此之外,我看的比较多的还有不同版本的Compute Capability的介绍,其中包括每个SM最多能同时处理的block数量,每个block最大的线程数……这些在实际调用kernel的时候都需要考虑。
Best Practices Guide介绍的优化技巧和硬件就比较相关了。特别是需要了解设备中的存储结构,因为很大部分情况下是在想办法降低访存的延时。比如Memory Optimizations这一章介绍的内容就非常值得细看。
- Ubuntu 20.04
- NVIDIA Driver Version 550.67
- CUDA Version 12.4
- Eigen repository-url
- cmake version 3.25.1
- gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
在开始之前需要有一台带有Nvidia显卡的主机,然后安装上驱动,最新的驱动可以从官网下载得到。直接运行然后按照指示进行安装即可,网上的教程需要用户手动去禁用nouveau,但现在这些操作驱动安装程序都可以完成,所以不需要额外的准备工作了(至少我安装的时候是这样的)。
驱动安装完成后再同样按照官网的指导步骤安装CUDA Toolkit。安装完成后再修改.zshrc或.bashrc将bin路径和lib路径添加到分别添加到PATH和LD_LIBRARY_PATH中。
export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
另外本项目依赖Eigen,因此还需要另外安装Eigen库。拉取源码后直接install即可。
在开始前需要确定显卡的Compute Capability,可通过官网查询。也可以先编译check_cc来获取当前设备的Compute Capability。(默认查询的是device 0 的设备信息)
mkdir build
cd build
cmake ..
make check_cc
我的设备用到了两种显卡,因此设置的CMAKE_CUDA_ARCHITECTURES是75和86,如果你的设备用的是其他的显卡,可以修改CMakeLists.txt,将CMAKE_CUDA_ARCHITECTURES修改成你需要的值。
切换到build目录下,make all即可。
本项目做的主要就是用Nvidia GPU实现两个NxN的双精度矩阵乘法,在common.h中,设置了N的大小以及thread block的大小。
主要内容:
- baseline - 最基础的矩阵乘法实现方式与eigen,cublas的实现进行对比;
- shared_memory - 用共享内存实现,减少访问global memory的次数;
- coalesce - 尽可能用coalesce的形式访存;减少访问shared memory的bank冲突;
- other_practice - 用capture graph执行矩阵乘法;用memory mapped方式执行矩阵乘法。