OpenCL和CUDA是两种异构计算的编程模型。
NVIDIA在2007年正式发布CUDA之后,一直大力推广这种编程模型,主要集中在科学计算这一块,原因是这个领域的很多应用程序属于数据并行类型,因此利用CUDA在NVIDIA自家的GPU上加速原来单线程的程序一般都能取得满意的加速效果。
OpenCL最早是由Apple提出,后来交给了Khronos这个开放标准组织。OpenCL 1.0 在2008年底正式由Khronos发布,比CUDA晚了整整一年。由于NVIDIA的CUDA取得了先机,OpenCL则不那么流行,玩的人比较少。
这两种异构计算模型,基本思想其实是非常接近的。我个人的观点是这两东东差别不大,所以学会其中一个,另一个则能触类旁通。网上有不少争论到底是CUDA还是OpenCL好,各种观点都有,其实是肥环瘦燕,各有所好。对初学者来说,可能CUDA可能更简单点,需要关注的东西相对少一点;OpenCL由于要考虑不同平台,要注意的方面多一点,个人觉得比较罗嗦,但目前又不可少。
本人背景不是搞计算机的,所以硬件软件的底层并不是太关心,关注的是这两种编程模型的具体实现,所以比较了一下两种模型的实施步骤
先来CUDA
- 在device (也就是GPU) 上申请内存
- 将host (也就是CPU) 上的数据拷贝到device
- 执行CUDA kernel function
- 将device上的计算结果传回host
- 释放device上的内存
记住这5大步,也就掌握了CUDA的基本思路。
来看看OpenCL
- 检测申请计算资源
- 检测platform
- 检测platform对应的device
- 建立context
- 建立command queue
- 在context内申请存储空间
- 将host (也就是CPU) 上的数据拷贝到device
- OpenCL代码编译
- 读入OpenCL (kernel function) 源代码
- 编译创立program 句柄
- 创立一个 OpenCL kernel 句柄
- 申明设置 kernel 的 参数
- 设置NDRange
- 运行kernel
- 将device上的计算结果传回host
- 释放计算资源
- 释放kernel
- 释放program
- 释放device memory
- 释放command queue
- 释放context
6大步骤,共10几个小步。
用OpenCL C的话,一个都不能少;用C++ wrapper的话可以稍微简单点,第6步不用程序员自己写了,C++的destructor会自动释放这些资源。
NIVIDIA在介绍OpenCL的时候,把它当作一种类似与CUDA driver API 的底层实现,将CUDA runtime API 称为一种高层实现。其实OpenCL和CUDA在很多方面是非常类似的。