OpenCL编程指南
1. 简介
OpenCL(Open Computing Language,开放计算语言)是一种开放的、跨平台的并行计算框架,由Khronos Group维护。它为开发者提供了统一的编程接口,使得应用程序可以在不同的硬件平台(CPU、GPU、DSP和其他处理器)上运行,从而提高了代码的可移植性和性能。OpenCL主要包含以下两个部分:
-
用于编写 kernels(在OpenCL设备上运行的函数) 的语言(基于C99)
-
用于定义并控制平台的API
如下图所示,OpenCL框架包含两个API:平台层(Platform Layer)API 和 运行时(Runtime)API。

-
平台层API在主机(Host)CPU上运行,主要用于查询和使能系统中可用的并行处理器或计算设备。通过查询可用的计算设备,应用程序可以移植到不同系统中运行,从而适应各种硬件加速设备的组合。
-
运行时API则使应用程序能够为其选定的计算设备编译内核程序,并将其并行加载到这些处理器上执行。内核程序执行完成后,运行时API还将用于收集和处理结果。
2. OpenCL程序的执行
OpenCL将内核程序视为可执行代码的基本单元(类似于C函数)。内核能够以数据并行或任务并行的方式执行。一个 OpenCL 程序是由多个内核和函数组成的集合(类似于具有运行时链接的动态库)。
OpenCL 命令队列由主机应用程序用于将内核和数据传输函数发送到设备以执行。通过将命令排队到命令队列中,内核和数据传输函数可以异步且并行地与主机应用程序代码一起执行。
命令队列中的内核和函数可以按顺序或乱序执行。一个计算设备可以拥有多个命令队列。
下图展示了执行OpenCL Kernel的流程:

执行 OpenCL 程序的完整步骤如下:
-
查询可用的 OpenCL 平台和设备
-
为一个或多个平台中的 OpenCL 设备创建上下文
-
为上下文中的 OpenCL 设备创建并构建程序
-
从程序中选择要执行的内核
-
为内核创建内存对象以进行操作
-
创建命令队列以在 OpenCL 设备上执行命令
-
获取执行结果并清理环境
更详细的介绍可以参考:
3. 主要API
3.1 OpenCL平台
选择OpenCL平台是OpenCL的第一步,clGetPlatformIDs()
这个API就是查找制定系统上的可用OpenCL平台的集合。
cl_int clGetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms)
-
num_entries:表示OpenCL平台的索引值。设置为0,且platforms为NULL时用于查询可用的平台数
-
platforms:表示平台的指针
-
num_platforms:表示OpenCL平台的数量,一般作为返回值
这个API一般会调用两次,用来查询和获取到对应的平台信息,使用方式如下:
cl_int err = 0; // 错误代码
cl_uint num_platform = 0; // 平台数量
cl_platform_id *platform = NULL; // 平台 ID 指针
err = clGetPlatformIDs(0, NULL, &num_platform); // 获取平台数量,第一个参数为要获取的平台数量,第二个参数为平台 ID 数组,第三个参数为返回的平台数量
if (err!= CL_SUCCESS) { // 检查错误
fprintf(stderr, "Failed to create context: %d\n", err); // 输出错误信息
exit(-1); // 退出程序
}
platform = (cl_platform_id*)malloc(sizeof(cl_platform_id) * num_platform); // 分配内存以存储平台 ID
err = clGetPlatformIds(num_platform, platform, NULL); // 获取平台 ID