OpenCL “速成”冲刺【第二天】
OpenCL结构与模型
OpenCL结构
上一天咱们最后写了一个OpenCL版本的Hello world程序,童鞋们肯定觉得复杂,一个hello world就这么多代码,其实不是这样的,大家注意到上边的程序包含两个部分,一个
cpp文件和一个cl文件,OpenCL的Hello world是要在GPU上执行的,那么cl就是在GPU上执行的代码(一般会比C语言代码复杂),而GPU程序是无法直接在GPU上执行的,
而cpp文件就是负责执行GPU程序环境的创建(也就是这部分代码不会随着程序复杂而增加很多,个人很容易封装),这两个文件其实就是最简单版本的OpenCL两个主要部分
的,异构平台的开发框架
(OpenCL API)和在异构处理器上的编程语言(Kernel)。
OpenCL模型
OpenCL主要定义了下面四种模型:平台模型,执行模型,内存模型,编程模型。
一般教材都是放到开头讲一下,个人感觉这样不利于理解,所以打算将概念分解到程序中去讲解。
(英文)http://www.khronos.org/registry/cl/specs/opencl-1.2.pdf
(中文)http://cloud.github.com/downloads/walkthetalk/contextstudy/opencl-spec-zh-beta2.pdf
PS:OpenCL最新版本是2.0,但是基本每个版本都是扩充,没有本质结构的修改,一般情况推荐阅读有2.0的上一个版本1.2。
目前准备平台模型主要在API部分讲,执行模型在kernel部分讲,内存模型在kernel优化部分讲,编程模型会提一下,不会讲太多。
主要内容会涉及opencl规范文档的前六章。
OpenCL API (一)
咱们对应上节课的程序开始讲解API,API部分不会讲解的太具体,因为大多是通用的,而且文档上足够详细。
首先说明的是一些通用性质的,因为说了OpenCL就是库文件和头文件,那么也就说命令OpenCL的头文件会包含很多有用的信息,咱们就从头文件开始讲解。
头文件包含5个部分。
第一部分,直接跳过,说明OpenCL是跨平台的,而且虽然可用于C++,但是C语言的API,当然也有C++版本的API,实际上用的很少,本教程也不会涉及。
- #ifdef __APPLE__
- #include <OpenCL/cl_platform.h>
- #else
- #include <CL/cl_platform.h>
- #endif
- #ifdef __cplusplus
- extern "C" {
- #endif
第二部分,自有类型定义,分两种情况,一种是定义的结构体类型,这些不需要深究,只要能在调用API时使用相应的类型就行,另一种是通用类型前面加上cl_代表是在OpenCL中使用的,这些类型是用常用数据类型通用的,使用cl_类型或者常用类型对程序没有影响,但是混合使用是非常不好的习惯,建议OpenCL相关的函数还是使用OpenCL类型。
- typedef struct _cl_platform_id * cl_platform_id;
- ...
- typedef cl_uint cl_bool;
- ...
- typedef cl_uint cl_profiling_info;
- ...
第三部分,错误代码,这是最重要的部分,一般API分两种形式,一种是执行操作,返回错误代码,例如clGetPlatformIDs,clBuildProgram,一直种是返回创建对象,但是最后一个参数是错误代码的,例如clCreateContext,clCreateKernel,也就是无论什么API都会返回一个cl_int的错误代码,0代表正确,负数代表各种错误,都有相应的说明,很好发现错误,配合文档中的API说明,多数错误都可以排除,所以说这是最重要的部分。
*曾经有位童鞋在网上说代码遇到了问题,我告诉他去看头文件错误代码,他还是弄不明白,还非得按他的思路死扣API的所有参数的含义,然后却连参数类型都弄不明白,然后我就直接劝他回去好好学学C语言了...
- #define CL_SUCCESS 0
- #define CL_DEVICE_NOT_FOUND -1
- #define CL_DEVICE_NOT_AVAILABLE -2
- ...
第四部分,属性定义,好多啊,而且用到的比较少,用到的碰到了相应的API再讲,跳过
第五部分,API的函数声明,有API忘记参数了,可以直接查,比翻文档速度快,也都有简易注释,用VS的话,自动提示参数也很方便。
- /* Kernel Object APIs */
- extern CL_API_ENTRY cl_kernel CL_API_CALL
- clCreateKernel(cl_program /* program */,
- const char * /* kernel_name */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
- ...
作业
(一)调试上节课程序,查看所有的ret值,进行下列操作,并查看错误返回值:
1.随便替换三个不同的API的某一个参数,查看返回值。
2.讲kernel里随便加点错误的代码,查看API的返回值。
3.修kernel的函数列表加上一个新参数,查看API的返回值。
(二)编写函数或者宏定义,检查返回值,并输出错误类型。