门户网站优化报价,淘宝刷单网站建设,公司简介宣传图,宁波建网站找哪家目录 1.前言 2.获取平台信息
1.cl_int类型
2.cl_platform_id类型
3.clGetPlatformIDs()#xff1a;查询系统OpenCL平台数量或获取具体的平台信息
4.clGetPlatformInfo()#xff1a;查询指定OpenCL平台的信息#xff0c;例如平台名称、供应商、版本等 3.设置OpenCL上下文…目录 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接口.pdfhttps://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_CPUCPU设备CL_DEVICE_TYPE_GPUGPU设备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_uintCL_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实现硬件级别乘加指令优化-Idir包含路径用于指定头文件的搜索目录-Werror将警告视为错误确保编译过程无警告-Dmacrovalue定义宏变量用于在源代码中进行条件编译
表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 //要释放的上下文对象
);