GPU架构
针对软硬件的架构组件是不同的概念,软件的架构是为了方便cuda编程而设计,GPU显卡会根据代码自动调用相应的硬件组件,先介绍软件层面的架构,即CUDA架构。
CUDA架构
众所周知,cuda可以做并行加速计算,具体怎么并行运算还要从其架构说起。
首先,CUDA的程序分为两个部分,host端和device端,host端代码实在cpu上执行,device端代码则是在显卡芯片上执行。host端主要负责数据准备,讲准备好的数据拷贝到显卡芯片上,进行计算,再从显卡上拷贝最终计算结果。
cpu在取显卡内存数据时,速度较慢,所以不能频繁从显卡拷贝数据,最好只拷贝一次最终的结果。
device端架构
在设备端架构主要由grid,block,thread三部分组成。
thread是最小的执行单位,block包括若干个thread,grid包含若干个block。
每个block中的thread执行的是相同的代码,能够存取同一块共享内存,但是一个block中thread个数是有限的。不同block中thread无法共享内存。
同理,一个gird中的block执行的也是相同的操作。
每个 thread 都有自己的一份 register 和 local memory 的空间。同一个 block 中的每个thread 则有共享的一份 share memory。此外,所有的 thread(包括不同 block 的 thread)都共享一份 global memory、constant memory、和 texture memory。不同的 grid 则有各自的 global memory、constant memory 和 texture memory。
并行计算的方式下,处理分支指令的性能会比较差。
GPU硬件架构
- 流处理器(Streaming Processor, SP):流处理器是GPU运算的最基本计算单元。一个SP中包括了多个核心(Core)和寄存器等组件构成,一个SP可以并行执行一个thread,也就是一个具体的指令任务。
- 流式多处理器(Streaming Multiprocessors,SM):GPU硬件实际上是一个SM阵列,一个GPU上有多个SM每个SM包括多个SP。
- 线程束(Warp):GPU一般将32个线程作为一个线程束。
具体硬件架构如下图所示。
一个和函数启动时,会将block分配到不同SM上执行,同一个block只能分配到一个SM上。此时一个SM上有多个block,一个block有多个线程(不同的硬件支持最大线程数不同),但是GPU设备实际执行时,在某一时刻,SM上只执行一个线程束,也就是32个线程在同时同步执行,线程束中的每个线程执行同一条指令。多个warps需要轮流进入SM,由SM的硬件warp scheduler负责调度。
Hello CUDA!
下面来实现第一个CUDA代码,主要是读取显卡的一些设备信息。
#include "cuda_runtime_api.h"
#include "cuda_func.h"
#include <iostream>
void cuda_info() {
int deviceCount;
cudaGetDeviceCount(&deviceCount);
std::cout << deviceCount << std::endl;
for(int i=0;i<deviceCount;i++)
{
cudaDeviceProp devProp;
cudaGetDeviceProperties(&devProp, i);
std::cout << "使用GPU device " << i << ": " << devProp.name << std::endl;
std::cout << "设备全局内存总量: " << devProp.totalGlobalMem / 1024 / 1024 << "MB" << std::endl;
std::cout << "SM的数量:" << devProp.multiProcessorCount << std::endl;
std::cout << "每个线程块的共享内存大小:" << devProp.sharedMemPerBlock / 1024.0 << " KB" << std::endl;
std::cout << "每个线程块的最大线程数:" << devProp.maxThreadsPerBlock << std::endl;
std::cout << "设备上一个线程块(Block)种可用的32位寄存器数量: " << devProp.regsPerBlock << std::endl;
std::cout << "每个EM的最大线程数:" << devProp.maxThreadsPerMultiProcessor << std::endl;
std::cout << "每个EM的最大线程束数:" << devProp.maxThreadsPerMultiProcessor / 32 << std::endl;
std::cout << "设备上多处理器的数量: " << devProp.multiProcessorCount << std::endl;
std::cout << "======================================================" << std::endl;
}
}
————————————————