OpenCL(贰):浅析CL内核程序接口函数
目录
1.前言
2.获取平台信息
1.cl_int类型
2.cl_platform_id类型
3.clGetPlatformIDs():查询系统OpenCL平台数量或获取具体的平台信息
4.clGetPlatformInfo():查询指定OpenCL平台的信息,例如平台名称、供应商、版本等
3.设置OpenCL上下文Context属性
1.cl_context_properties类型
4.创建上下文
1.cl_context类型
2.clCreateContextFromType():用于根据设备类型创建上下文的函数
5.寻找OpenCL设备(GPU)
1.cl_device_id类型
2.clGetContextInfo():用于查询上下文cl_context的相关信息
6.创建CL内核函数
7.装载内核程序
1.cl_program类型
2.clCreateProgramWithSource():用于创建一个程序对象,该程序对象包含OpenCL C源代码
8.生成CL程序并获取实例句柄
1.cl_kernel类型
2.clBuildProgram():用于编译OpenCL程序对象,生成针对目标设备的执行代码
9.创建命令队列和缓冲区
1.cl_command_queue类型
2.cl_mem类型
3.clCreateCommandQueue():创建一个命令队列,用于在指定的 OpenCL 设备上执行命令
4.clCreateBuffer():创建一个 OpenCL 缓冲区内存对象,用于在 OpenCL 设备上存储数据
10.将参数传入内核程序并传入命令队列
1.clSetKernelArg(): 用于为 OpenCL 内核的特定参数设置参数值。在执行内核之前,必须为内核的所有参数设置值
2.clEnqueueNDRangeKernel() :用于将内核执行命令排队到命令队列中
11.执行命令队列并保存至主机
1.clFinish() :用于确保命令队列中的所有命令都已执行完毕。会阻塞主机线程,直到命令队列中的所有命令都完成执行
2.clEnqueueReadBuffer():用于将数据从设备的缓冲区读取到主机内存中。它可以是阻塞或非阻塞的,具体取决于blocking_read参数
12.释放资源
1.clReleaseKernel():减少指定内核对象的引用计数。当引用计数降为零时,内核对象将被释放
2.clReleaseProgram():减少指定程序对象的引用计数。当引用计数降为零时,程序对象及其构建的对象(如内核)将被释放
3.clReleaseMemObject():减少指定内存对象的引用计数。当引用计数降为零时,内存对象将被释放
4.clReleaseCommandQueue():减少指定命令队列的引用计数。当引用计数降为零时,命令队列将被释放
5.clReleaseContext():减少指定上下文对象的引用计数。当引用计数降为零时,上下文及其关联的所有对象(如命令队列、内存对象、程序对象和内核对象)都将被释放
前言
紧接文章《OpenCL(壹):了解OpenCL模型到编写第一个CL内核程序》的内容,本篇文章将针对上一篇提到的第一个CL内核程序中的函数接口进行刨析,解释每一个接口文档的作用。当然这或许比不上官方的文档,但是详细的解析有利于后续开发的翻阅,只有做好归纳总结才能为己所用,在开发中遇到的问题也会迎刃而解。附官方文档链接:
OpenCL2.1接口https://registry.khronos.org/OpenCL/sdk/2.1/docs/man/xhtml/OpenCL2.1接口.pdf
https://registry.khronos.org/OpenCL/sdk/2.1/docs/OpenCL-2.1-refcard.pdf
获取平台信息
根据前文的程序,我们在main函数中第一步操作是获取平台的详细,代码如下:
cl_int status = 0; //记录函数状态
size_t deviceListSize; //记录设备个数
cl_uint numPlatforms; //可用平台数量
cl_platform_id platform = NULL; //存储平台ID
status = clGetPlatformIDs(0, NULL, &numPlatforms); //获取平台个数
if (status != CL_SUCCESS) { std::cout << "错误:获取设备失败" << std::endl;return EXIT_FAILURE;
}if (numPlatforms > 0) { //个数大于0则便利平台信息cl_platform_id* platforms = (cl_platform_id*)malloc(numPlatforms * sizeof(cl_platform_id)); //创建内存存储平台信息status = clGetPlatformIDs(numPlatforms, platforms, NULL); //获取平台IDif (status != CL_SUCCESS) {std::cout << "错误:获取平台ID失败" << std::endl;return -1;}for (unsigned int i = 0; i < numPlatforms; ++i) { //遍历平台列表获取平台信息char pbuff[100];status = clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, sizeof(pbuff), pbuff, NULL); //获取平台信息platform = platforms[i];if (!strcmp(pbuff, "GPU")) { break;}}delete platforms;
}
在这段代码中分别提到了几种OpenCL中的类型和函数,以下是具体的解释:
类型名称 | 含义 | 64位平台大小 |
cl_int类型 | 一个 32 位的有符号整数,用于返回状态码或作为参数的整型变量 | 4字节 |
cl_platform_id类型 | 句柄类型,用于标识一个特定的OpenCL平台 | 8字节 |
表1.OpenCL中的特定类型
clGetPlatformIDs():查询系统OpenCL平台数量或获取具体的平台信息
cl_int clGetPlatformIDs(cl_uint num_entries, //指定存储的平台数量的对象cl_platform_id *platforms, //指定存储平台ID的对象cl_uint *num_platforms //指定存储返回平台总数的对象
);返回值类型:cl_int1.CL_SUCCESS:函数成功执行。2.CL_INVALID_VALUE:传递的参数值无效。例如num_entries为0而platforms不为NULL3.CL_OUT_OF_HOST_MEMORY:主机内存不足,无法完成操作
clGetPlatformInfo():查询指定OpenCL平台的信息,例如平台名称、供应商、版本等
cl_int clGetPlatformInfo(cl_platform_id platform, //指定要查询的OpenCL平台cl_platform_info param_name, //指定要查询的平台属性size_t param_value_size, //指定param_value缓存的大小void *param_value, //指向用于存储返回值的内存地址size_t *param_value_size_ret //存储返回实际写入param_value的字节数
);返回值类型:cl_int1.CL_SUCCESS:函数成功执行。2.CL_INVALID_VALUE:传递的参数值无效。例如num_entries为0而platforms不为NULL3.CL_OUT_OF_HOST_MEMORY:主机内存不足,无法完成操作
针对该接口函数中存在的cl_platform_info类型作以下补充:
枚举值 | 含义 |
CL_PLATFORM_PROFILE | 返回平台的配置文件 |
CL_PLATFORM_VERSION | 返回平台的OpenCL版本 |
CL_PLATFORM_NAME | 返回台的名称 |
CL_PLATFORM_VENDOR | 返回平台的供应商名称 |
CL_PLATFORM_EXTENSIONS | 返回平台支持的扩展列表 |
CL_PLATFORM_HOST_TIMER_RESOLUTION | 返回主机定时器的分辨率/纳秒(2.1版本) |
CL_PLATFORM_NUMERIC_VERSION | 返回平台的OpenCL版本号(3.1版本) |
CL_PLATFORM_EXTENSIONS_WITH_VERSION | 返回支持的扩展及其版本(3.0版本) |
表2.l_platform_info类型的补充
设置OpenCL上下文Context属性
后续的小节都会根据编写的OpenCL程序代码进行讲解,就不再对其进行赘述
cl_context_properties cps[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0 };
cl_context_properties* cprops = (NULL == platform) ? NULL : cps;
//Tip:此处的NULL == platform写法可以预防错误的代码编写导致赋值操作
类型名称 | 含义 | 64位平台大小 |
cl_context_properties类型 | 上下文属性类型,用于在创建上下文时配置额外的信息 | 8字节 |
表3.OpenCL中的cl_context_properties类型
补充以下针对cl_context_properties中的枚举类描述:
枚举量 | 含义 |
CL_CONTEXT_PLATFORM | 指定上下文关联的平台 |
CL_GL_CONTEXT_KHR | 与OpenGL上下文共享的OpenGL上下文句柄 |
CL_EGL_DISPLAY_KHR | 指定 EGL 显示的句柄,用于OpenCL和EGL的互操作 |
CL_CONTEXT_INTEROP_USER_SYNC | 用于设置用户同步标志,指定 OpenCL 和其他图形 API 是否需要手动同步(布尔值) |
表4.cl_context_properties中的枚举类描述
创建上下文
cl_context context = clCreateContextFromType(cprops, CL_DEVICE_TYPE_GPU, NULL, NULL, &status);
if (status != CL_SUCCESS) {std::cout << "错误:为GPU生成上下文失败" << std::endl;return EXIT_FAILURE;
}
针对此段代码中提到类型cl_context做以下解释:
类型名称 | 含义 | 64位平台大小 |
cl_context类型 | OpenCL中上下文类型,用于管理设备、内存、程序和命令队列等资源 | 8字节 |
表5.cl_context类型的补充
clCreateContextFromType():用于根据设备类型创建上下文的函数
cl_context clCreateContextFromType(const cl_context_properties *properties, //指定上下文的属性列表,通常用于指定平台cl_device_type device_type, //指定要包含的设备类型void (CL_CALLBACK *pfn_notify)(const char *errinfo, const void *private_info, size_t cb, void *user_data), //错误通知回调函数,当上下文在运行时发生错误时调用void *user_data, //传递给回调函数的用户数据,可用于上下文特定的操作cl_int *errcode_ret //返回错误代码的指针。如果为NULL,错误代码将被忽略
);返回值:cl_context
成功时返回创建的OpenCL上下文,失败时返回 NULL
在函数中存在一个cl_device_type类型,具体解释如下:
枚举值 | 含义 |
CL_DEVICE_TYPE_DEFAULT | 默认设备类型(由平台决定) |
CL_DEVICE_TYPE_CPU | CPU设备 |
CL_DEVICE_TYPE_GPU | GPU设备 |
CL_DEVICE_TYPE_ACCELERATOR | 专用加速器设备 |
CL_DEVICE_TYPE_CUSTOM | 自定义设备 |
CL_DEVICE_TYPE_ALL | 所有可用设备 |
表6.cl_device_type类型
寻找OpenCL设备(GPU)
//获取设备个数
status = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &deviceListSize);
if (status != CL_SUCCESS) {std::cout << "错误:寻找可用的设备个数失败" << std::endl;return EXIT_FAILURE;
}
cl_device_id* devices = (cl_device_id*)malloc(deviceListSize);
if (devices == 0) {std::cout << "错误:当前可用设备数为0" << std::endl;return EXIT_FAILURE;
}//获取设备列表
status = clGetContextInfo(context, CL_CONTEXT_DEVICES, deviceListSize, devices, NULL);
if (status != CL_SUCCESS) {std::cout << "错误:获取设备信息失败" << std::endl;return EXIT_FAILURE;
}
针对代码中的cl_device_id类型作以下解释:
类型名称 | 含义 | 64位平台大小 |
cl_device_id类型 | 句柄类型,用于表示OpenCL设备的唯一标识符 | 8字节 |
表7.cl_device_id类型
clGetContextInfo():用于查询上下文cl_context的相关信息
cl_int clGetContextInfo(cl_context context, //指定要查询的OpenCL上下文cl_context_info param_name, //指定要查询的信息类型size_t param_value_size, //指定param_value缓冲区的大小void *param_value, //存储返回的参数值size_t *param_value_size_ret //返回实际写入的字节数
);返回值类型:cl_int1.CL_SUCCESS:函数成功执行。2.CL_INVALID_VALUE:传递的参数值无效。例如num_entries为0而platforms不为NULL3.CL_OUT_OF_HOST_MEMORY:主机内存不足,无法完成操作
在函数中存在cl_context_info枚举类型,指定该枚举类型主要用于设置返回值param_value的类型,对此作以下解释:
枚举值 | 含义 | param_value的类型 |
CL_CONTEXT_REFERENCE_COUNT | 上下文的引用计数,表示当前引用该上下文的对象数量 | cl_uint |
CL_CONTEXT_DEVICES | 与上下文关联的设备列表 | cl_device_id[] |
CL_CONTEXT_PROPERTIES | 上下文的属性列表,包括平台信息或其他属性 | cl_context_properties[] |
CL_CONTEXT_NUM_DEVICES | 上下文中设备的数量 | cl_uint |
表8.cl_context_info枚举类型
创建CL内核函数
#define KERNEL(...)#__VA_ARGS__ //使用#__VA_ARGS_宏将传入KERNEL宏的实参转为字符串//编写内核函数,该内核函数将转换为字符串并由指针kernelSourseCode指向
const char* kernelSourceCode = KERNEL(__kernel void wildpointer(__global uint * buffer) { //__kernel用于声明OpenCL内核函数size_t gidx = get_global_id(0);size_t gidy = get_global_id(1);size_t lidx = get_local_id(0);buffer[gidx + 4 * gidy] = (1 << gidx) | (0x10 << gidy);}
);
这段代码主要是将我们需要使用GPU执行的函数转换为字符串,后续通过将函数和参数传入内核程序来指定运行内容,其中要注意的是我们编写的CL内核函数为wildpointer,这在后续我们获取内核实例的句柄需要保持一致。我们也可以不使用这种方式编写内核函数,我们可以编写一个cl文件在需要载入内核程序时进行调用
装载内核程序
//装载内核程序,编译CL程序,生成OpenCL内核实例
size_t sourceSize[] = { strlen(kernelSourceCode) }; //获取函数字符串长度
cl_program program = clCreateProgramWithSource(context, 1, &kernelSourceCode, sourceSize, &status);
if (status != CL_SUCCESS) {std::cout << "错误:将二进制文件装载到内核程序失败" << std::endl;return EXIT_FAILURE;
}
在这段代码中,存在一个cl_program类型,具体解释如下:
类型名称 | 含义 | 64位平台大小 |
cl_program类型 | 用于表示一个OpenCL程序对象,并可通过编译、链接生成可执行的OpenCL内核 | 8字节 |
表9.cl_program类型
clCreateProgramWithSource():用于创建一个程序对象,该程序对象包含OpenCL C源代码
cl_program clCreateProgramWithSource(cl_context context, //程序对象的上下文cl_uint count, //函数的字符长度const char **strings, //指向包含OpenCL C源代码的指针const size_t *lengths, //每个字符串的长度数组cl_int *errcode_ret //返回函数的错误码
);返回值类型:cl_program
成功时返回创建的程序对象,失败时返回NULL
生成CL程序并获取实例句柄
//为指定的OpenCL设备生成CL程序
status = clBuildProgram(program, 1, devices, NULL, NULL, NULL);
if (status != CL_SUCCESS) {std::cout << "错误:编译CL程序失败" << std::endl;return EXIT_FAILURE;
}//获取内核实例的句柄
cl_kernel kernel = clCreateKernel(program, "wildpointer", &status);
if (status != CL_SUCCESS) {std::cout << "错误:在程序上初始化内核程序失败" << std::endl;return EXIT_FAILURE;
}
在代码中存在一个cl_kernel类型,具体解释如下:
类型名称 | 含义 | 64位平台大小 |
cl_kernel类型 | 表示一个内核对象的句柄类型。内核是 OpenCL 程序的基本执行单位,通常是一个通过编译后生成的函数,用来在设备上执行计算任务 | 8字节 |
表10.cl_kernel类型
clBuildProgram():用于编译OpenCL程序对象,生成针对目标设备的执行代码
cl_int clBuildProgram(cl_program program, //要编译的OpenCL程序对象cl_uint num_devices, //编译程序的设备个数const cl_device_id *device_list, //设备列表const char *options, //编译时的选项字符串,例如优化选项、定义宏等void (*pfn_notify)(cl_program, void *user_data), //回调函数指针,在编译后调用void *user_data //传递给回调函数的参数
);返回值类型:cl_int1.CL_SUCCESS:函数成功执行2.CL_INVALID_PROGRAM:无效的程序对象3.CL_INVALID_DEVICE:无效的词语4.CL_INVALID_VALUE:传递的参数值无效。例如num_entries为0而platforms不为NULL5.CL_OUT_OF_HOST_MEMORY:主机内存不足,无法完成操作
参数options的选项见下表:
选项 | 含义 |
-cl-fast-relaxed-math | 快速浮点计算,用于性能优先的浮点计算 |
-cl-no-signed-zeros | 简化符号的处理逻辑,无法使用+0和-0 |
-cl-mad-enable | 实现硬件级别乘加指令优化 |
-I<dir> | 包含路径,用于指定头文件的搜索目录 |
-Werror | 将警告视为错误,确保编译过程无警告 |
-D<macro>=<value> | 定义宏变量,用于在源代码中进行条件编译 |
表11.参数options
创建命令队列和缓冲区
//创建OpenCL命令队列
cl_command_queue commandQueue = clCreateCommandQueue(context, devices[0], 0, &status);
if (status != CL_SUCCESS) {std::cout << "错误:初始化命令队列失败" << std::endl;return EXIT_FAILURE;
}//创建OpenCL缓冲区
unsigned int* outbuffer = new unsigned int[4 * 4];
memset(outbuffer, 0, 4 * 4 * 4);
cl_mem outputBuffer = clCreateBuffer(context, CL_MEM_ALLOC_HOST_PTR, 4 * 4 * 4, NULL, &status);
if (status != CL_SUCCESS) {std::cout << "错误:初始化OpenCL缓冲区失败" << std::endl;return EXIT_FAILURE;
}
在代码中存在一个cl_command_queue和cl_mem类型,具体解释如下:
类型名称 | 含义 | 64位平台大小 |
cl_command_queue类型 | 命令队列类型,用于在OpenCL设备上执行命令,确保命令按顺序执行,如内核执行、内存传输等 | 8 字节 |
cl_mem类型 | 内存对象类型,用于在OpenCL设备上存储数据,允许数据在主机和设备之间进行传输,可以是缓冲区、图像等 | 8 字节 |
表12.cl_command_queue和cl_mem类型
clCreateCommandQueue():创建一个命令队列,用于在指定的 OpenCL 设备上执行命令
cl_command_queue clCreateCommandQueue(cl_context context, //OpenCL上下文,指定命令队列将要使用的设备和环境cl_device_id device, //指定命令队列将要执行命令的设备cl_command_queue_properties properties, //命令队列的属性,用于指定命令队列的行为cl_int *errcode_ret //返回函数的错误码
);返回值类型:cl_command_queue
返回一个 cl_command_queue 类型的指针,指向创建的命令队列对象。如果创建失败,返回 NULL
参数cl_command_queue_properties的选项见下表:
选项 | 含义 |
CL_QUEUE_OUT_OF_ORDER_EXCE_MODE_ENABLE | 无序执行命令 |
CL_QUEUE_PROFILING_ENABLE | 命令队列中的命令将启用性能分析 |
CL_QUEUE_ON_DEVICE | 指示这是一个设备队列 |
CL_QUEUE_ON_DEVICE_DEFAULT | 默认的设备队列 |
clCreateBuffer():创建一个 OpenCL 缓冲区内存对象,用于在 OpenCL 设备上存储数据
cl_mem clCreateBuffer(cl_context context, //OpenCL上下文,指定命令队列将要使用的设备和环境cl_mem_flags flags, //内存对象的标志,用于指定内存对象的访问权限和行为size_t size, //内存对象的大小void *host_ptr, //指向主机内存的指针,NULL则在设备上分配内存;非NULL则使用主机内存cl_int *errcode_ret //返回函数的错误码
);
参数cl_mem_flags的选项见下表:
选项 | 含义 |
CL_MEM_READ_WRITE | 默认标志,指定内存对象可以被内核读写 |
CL_MEM_WRITE_ONLY | 指定内存对象只能被内核写入,不能读取 |
CL_MEM_READ_ONLY | 指定内存对象只能被内核读取,不能写入 |
CL_MEM_USE_HOST_PTR | 只有在host_ptr不为NULL时有效。指示OpenCL实现使用host_ptr指向的内存作为内存对象的存储 |
CL_MEM_ALLOC_HOST_PTR | 指示OpenCL实现从主机可访问的内存中分配内存 |
CL_MEM_COPY_HOST_PTR | 只有在host_ptr不为NULL时有效。指示OpenCL实现为内存对象分配内存,并从host_ptr指向的内存中复制数据 |
将参数传入内核程序并传入命令队列
//将参数传入内核程序
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void*)&outputBuffer);
if (status != CL_SUCCESS) {std::cout << "错误:设置内核参数失败" << std::endl;return EXIT_FAILURE;
}//将内核程序插入命令队列
size_t globalThreads[] = {4, 4};
size_t localThread[] = {2, 2};
status = clEnqueueNDRangeKernel(commandQueue, kernel, 2, NULL, globalThreads, localThread, 0, NULL, NULL);
if (status != CL_SUCCESS) {std::cout << "错误:内核程序插入命令队列失败" << std::endl;return EXIT_FAILURE;
}
clSetKernelArg(): 用于为 OpenCL 内核的特定参数设置参数值。在执行内核之前,必须为内核的所有参数设置值
cl_int clSetKernelArg(cl_kernel kernel, //内核程序对象cl_uint arg_index, //参数的索引,从0开始,表示内核参数列表中的位置size_t arg_size, //参数值的大小const void *arg_value //指向参数值的指针
);返回值类型:cl_int1.CL_SUCCESS:函数成功执行2.CL_INVALID_PROGRAM:无效的程序对象3.CL_INVALID_DEVICE:无效的词语4.CL_INVALID_VALUE:传递的参数值无效。例如num_entries为0而platforms不为NULL5.CL_OUT_OF_HOST_MEMORY:主机内存不足,无法完成操作
clEnqueueNDRangeKernel() :用于将内核执行命令排队到命令队列中
cl_int clEnqueueNDRangeKernel(cl_command_queue command_queue, //命令队列对象cl_kernel kernel, //执行的内核程序对象cl_uint work_dim, //工作项的维度,范围为1到3const size_t *global_work_offset, //全局工作项的起始偏移量const size_t *global_work_size, //每个维度的全局工作项数量const size_t *local_work_size, //每个工作组中的工作项数量cl_uint num_events_in_wait_list, //等待事件列表中的事件数量const cl_event *event_wait_list, //事件对象列表,用于等待之前的一些事件完成cl_event *event //用于异步传输的事件对象
);返回值类型:cl_int1.CL_SUCCESS:函数成功执行2.CL_INVALID_PROGRAM:无效的程序对象3.CL_INVALID_DEVICE:无效的词语4.CL_INVALID_VALUE:传递的参数值无效。例如num_entries为0而platforms不为NULL5.CL_OUT_OF_HOST_MEMORY:主机内存不足,无法完成操作
执行命令队列并保存至主机
//执行命令队列中的命令
status = clFinish(commandQueue);
if (status != CL_SUCCESS) {std::cout << "错误:完全命令队列" << std::endl;return EXIT_FAILURE;
}//将设备的缓冲区中的数据保存至主机
status = clEnqueueReadBuffer(commandQueue, outputBuffer, CL_TRUE, 0, 4 * 4 * 4, outbuffer, 0, NULL, NULL);
if (status != CL_SUCCESS) {std::cout << "错误:读取缓冲区队列失败" << std::endl;return EXIT_FAILURE;
}
clFinish() :用于确保命令队列中的所有命令都已执行完毕。会阻塞主机线程,直到命令队列中的所有命令都完成执行
cl_int clFinish(cl_command_queue command_queue //命令队列对象,指定了要等待其命令完成的队列
);返回值类型:cl_int1.CL_SUCCESS:函数成功执行2.CL_INVALID_PROGRAM:无效的程序对象3.CL_INVALID_DEVICE:无效的词语4.CL_INVALID_VALUE:传递的参数值无效。例如num_entries为0而platforms不为NULL5.CL_OUT_OF_HOST_MEMORY:主机内存不足,无法完成操作
clEnqueueReadBuffer():用于将数据从设备的缓冲区读取到主机内存中。它可以是阻塞或非阻塞的,具体取决于blocking_read
参数
cl_int clEnqueueReadBuffer(cl_command_queue command_queue, //命令队列对象cl_mem buffer, //数据缓冲区对象cl_bool blocking_read, //指示读取操作是否阻塞size_t offset, //缓冲区中的偏移量size_t size, //读取的数据大小void *ptr, //指向主机内存的指针,用于存储读取的数据cl_uint num_events_in_wait_list, //等待事件列表中的事件数量const cl_event *event_wait_list, //事件对象列表,用于等待这些事件完成后再执行读取命令cl_event *event //事件对象,用于查询读取命令的执行状态
);返回值类型:cl_int1.CL_SUCCESS:函数成功执行2.CL_INVALID_PROGRAM:无效的程序对象3.CL_INVALID_DEVICE:无效的词语4.CL_INVALID_VALUE:传递的参数值无效。例如num_entries为0而platforms不为NULL5.CL_OUT_OF_HOST_MEMORY:主机内存不足,无法完成操作
释放资源
status = clReleaseKernel(kernel);
status = clReleaseProgram(program);
status = clReleaseMemObject(outputBuffer);
status = clReleaseCommandQueue(commandQueue);
status = clReleaseContext(context);
clReleaseKernel():减少指定内核对象的引用计数。当引用计数降为零时,内核对象将被释放
cl_int clReleaseKernel(cl_kernel kernel //要释放的内核对象
);
clReleaseProgram():减少指定程序对象的引用计数。当引用计数降为零时,程序对象及其构建的对象(如内核)将被释放
cl_int clReleaseProgram(cl_program program //要释放的程序对象
);
clReleaseMemObject():减少指定内存对象的引用计数。当引用计数降为零时,内存对象将被释放
cl_int clReleaseMemObject(cl_mem memobj //要释放的内存对象,例如缓冲区或图像
);
clReleaseCommandQueue():减少指定命令队列的引用计数。当引用计数降为零时,命令队列将被释放
cl_int clReleaseCommandQueue(cl_command_queue command_queue //要释放的命令队列
);
clReleaseContext():减少指定上下文对象的引用计数。当引用计数降为零时,上下文及其关联的所有对象(如命令队列、内存对象、程序对象和内核对象)都将被释放
cl_int clReleaseContext(cl_context context //要释放的上下文对象
);