错误处理、cuda模型、GPU架构杂谈
错误处理
所有编程都需要对错误进行处理,早起的编码错误,编译器会帮搞定,内存错误也能观察出来,但是有些逻辑错误很难发现,甚至到了上线运行时才会被发现,而且有些厉害的bug复现会很难,不总出现,但是很致命,而且CUDA基本都是异步执行的,当错误出现的时候,不一定是哪一条指令触发的,这一点非常头疼;这时候就需要对错误进行防御性处理了,例如代码库头文件里面的这个宏:
#define CHECK(call)\
{\
const cudaError_t error=call;\
if(error!=cudaSuccess)\
{\
printf("ERROR: %s:%d,",__FILE__,__LINE__);\
printf("code:%d,reason:%s\n",error,cudaGetErrorString(error));\
exit(1);\
}\
}
就是获得每个函数执行后的返回结果,然后对不成功的信息加以处理,CUDA C 的API每个调用都会返回一个错误代码,这个代码就可以好好利用了,当然在release版本中可以去除这部分,但是开发的时候一定要有的。
CUDA执行模型概述
开始接近CUDA最核心的部分,就是有关硬件,和程序的执行模型,用CUDA的目的其实说白了就是为计算速度快,所以压榨性能,提高效率其实就是CUDA学习的最终目的,没人学CUDA为了去显示Hello world。
启动核函数,计时,统计时间,然后学习了线程,内存模型,线程内存部分会在后面用几章的篇幅进行大书特书,而本章,介绍最底层最优理论指导意义的知识。
什么时候沿着硬件设计的思路设计程序,就会得到百战百胜;什么时候背离了硬件设计的思路去设计程序,就会得不到好结果。
CUDA执行模型概述
CUDA执行模型揭示了GPU并行架构的抽象视图,再设计硬件的时候,其功能和特性都已经被设计好了,然后去开发硬件,如果这个过程模型特性或功能与硬件设计有冲突,双方就会进行商讨妥协,知道最后产品定型量产,功能和特性算是全部定型,而这些功能和特性就是变成模型的设计基础,而编程模型又直接反应了硬件设计,从而反映了设备的硬件特性。
比如,最直观的一个就是内存,线程的层次结构帮助控制大规模并行,这个特性就是硬件设计最初设计好,然后集成电路工程师拿去设计,定型后程序员开发驱动,然后在上层可以直接使用这种执行模型来控制硬件。
所以了解CUDA的执行模型,可以帮助优化指令吞吐量,和内存使用来获得极限速度。
GPU架构概述
GPU架构是围绕一个流式多处理器(SM)的扩展阵列搭建的。通过复制这种结构来实现GPU的硬件并行,如图1所示。
图1 GPU流式多处理器(SM),复制这种结构实现GPU的硬件并行
图1包括关键组件:
1)CUDA核心
2)共享内存/一级缓存
3)寄存器文件
4)加载/存储单元
5)特殊功能单元
6)线程束调度器