参考,侵删
(48条消息) CUDA编程入门极简教程_小白将-CSDN博客_cuda编程
CUDA是建立在NVIDIA的CPUs上的一个通用并行计算平台和编程模型,基于CUDA编程可以利用GPUs的并行计算引擎来更加高效的解决比较复杂的计算难题。
CUDA是NVIDIA公司所开发的GPU编程模型,提供了GPU编程的简易接口,基于CUDA编程可以构建基于GPU运算的应用程序。CUDA提供了对C\C++、python、Fortran等编程语言的支持。
在基于CPU+GPU的异构计算平台中,CPU与CPU协同工作,CPU称为主机端(host),GPU称为设备端(device),CPU负责处理逻辑复杂的串行程序,GPU重点处理数据密集型的并行计算程序。
CUDA程序的执行流程:
host指代CPU及其内存,device指代GPU及其内存。host程序运行在CPU上,device程序运行在GPU上。host和device程序可以互相通信,可以相互之间进行数据拷贝。
- host程序运行在CPU上,device程序运行在GPU上
- 为数据在host(CPU的内存)中分配内存,并进行数据初始化
- 为数据在device(GPU的内存)中分配内存,并将数据从host拷贝到device上
- 调用CUDA的核函数在device上完成指定的运算
- 将device上的结果拷贝到host上
- 释放host和device上分配的内存
在CUDA中,通过函数类型限定词区别host和device上的函数。限定词_global_和_device_在device上执行,限定词_host_在host上执行。
kernel是在device上线程中并行执行的函数,一般从host中调用,核函数kernel用_global_符号声明,调用核函数kernel时要用<<<grid,block>>>来指定kernel要执行的线程数量。核函数返回类型必须是void,且不支持可变参数。_global_定义的kernel是异步的,这意味着host不会等待kernel执行完就执行下一步。
_device_,在device上执行,仅可在device上调用,不可以和_global_同时用。
_host_,在host上执行,仅可在host上调用,不可以和_global_同时用,但可以和_device—_同时用。
kernel线程层次结构
网格--->线程块--->线程
GPU上有许多并行化的轻量级线程,kernel在device上执行时实际上时启动了一个网格中的所有线程。
一个线程通过内置的坐标threadIdx来唯一表示它在线程块中的位置,一个线程呢个块通过blockIdx来标识线程块在网格中的位置。一个线程块中的线程是放在同一个流式多处理器上的,但是单个流式多处理器的资源有限,所以线程块中的线程数也是有限制的。要获取一个线程在线程块中的全局ID,可以通过线程内置变量blockDim来获得线程块各个维度大小,进而计算线程在线程块中的全局ID。线程呢个还有内置变量gridDim,用于获得网格块各个维度的大小。
##kernel在调用时需要通过执行配置<<<grid,block>>>来指定kernel所使用的线程数及结构。
CUDA内存模型
每个线程都有自己的私有本地内存,每个线程块都包含共享内存,还有所有线程都可以访问的全局内存、常量内存、纹理内存等。
GPU硬件层次
一个kernel实际上会启动很多线程,这些线程逻辑上并行,但是物理上网格中的线程块被完整的分配到流式处理器上,一个流失处理器上可以调度一个或多个线程块。SM并行的能力取决于SM的资源数,如CUDA核心、共享内存,寄存器等。所以grid知识逻辑层,SM才是执行的物理层。SM的基本执行单元是单指令多线程SIMT架构包含32个线程的线程束。GPU规定线程束中的线程在同一周期执行相同的指令。所以分配到SM的线程块,实际上被划分为线程束来并发执行,但是一个SM同时并发的线程束数是有限的,所以SM的配置会影响其所支持的线程块和线程束的并发数量。
总之,网格和线程块只是逻辑划分,一个kernel的所有线程在物理层不一定是同时并发的。所以kernel的grid和block的配置不同,性能会出现差异。由于SM基本执行单元是包含32个线程的线程束,所以block大小一般要设置为32的倍数。
查看GPU配置,如GPU型号、SM数量、线程束、共享内存等参数的方法见参考文章