OpenCL异构并行计算编程笔记(1):平台、设备与上下文
需要注意的是,不同于其他第三方库,OpenCL只提供一个开放API的规范,仅仅定义了接口,但并没有进行实现,各个接口的实现由处理器生产厂商自己完成。所以,虽然包括Intel、AMD以及Nvidia在内的厂商都对OpenCL提供了支持,但其实现的方法却各有不同,使得在不用品牌的处理器上使用OpenCL时需要使用特定的SDK,同时在特性上会略微有所不同(但基本不会产生太大影响)。接下来就简单介绍一下基于OpenCL的异构编程方法,在进行OpenCL编程之前,最好先了解OpenCL的架构模型,具体资料可参考:从零开始学习OpenCL开发架构,在此不予赘述。(实例环境:Windows10、Visual Studio 2015、OpenCL 1.1、Intel Core i5 3437U、Nvidia GeForce 840M)
一、获取平台(Platform):
不同厂商对于OpenCL具体的实现不同,某个厂商对于OpenCL的实现就形成了一个平台。不同厂商的处理器只能在不同的平台上运行,换句话说一个平台上只用运行实现该平台厂商的处理器。例如Intel、AMD和Nvidia均对OpenCL进行了自己的实现,在Intel的平台上可以同时使用Intel的CPU和GPU,但无法使用AMD和Nvidia的处理器;同样在AMD的平台上无法使用Intel和Nvidia二者的设备。在进行OpenCL编程时需要首先确定所选择的平台。
查询平台ID可以使用:
clGetPlatFormIDs(cl_uint num_entries, cl_platform_id*platforms, cl_uint *num_platforms)
该函数的第一个参数是platforms可以保存的平台ID的数目;
第二个参数是一个指针,用来保存找到的平台;
第三个参数保存查询到的平台的个数。
当返回值为0时,标志程序执行完成;非0时,为错误码。
通常可以使用两次该函数来获取所有的平台ID:
- cl_int ret; //用于保存函数返回值
- cl_uint num_platform; //用于保存平台个数
- cl_platform_id *platform //用于保存平台ID
- //
- //获取函数个数
- ret = clGetPlatformIDs(NULL, NULL, &num_platform);
- //
- //为platform分配空间
- platform = new cl_platform_id[num_platform];
- //获取所有平台
- ret = clGetPlatformIDs(num_platform, platform, NULL);
查询平台信息可以使用:
cl_int clGetDeviceIDs(cl_platform_id platform,
cl_platform_info param_name,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret)
该函数的第一个参数是之前获取的平台ID;
第二个参数是一个枚举体,用来标识所要查询的信息;
第三个参数是一个指针,用来存放查询到的信息;
第四个参数表示指针所指内存的大小;
第五个参数用来存放查询到的信息数据的大小。
同样,通常使用两次该函数来获取平台信息:
- cl_int ret; //用于保存函数返回值
- size_t ext_size; //用于保存平台信息大小
- char *ext_data; //用于保存平台信息
- cl_platform_info platform_info = CL_PLATFORM_NAME; //设置所要查询的信息
- //
- //获取平台信息大小
- ret = clGetPlatformInfo(platform[order], platform_info, 0, NULL, &ext_size);
- //
- //为ext_data分配空间
- ext_data = new char[ext_size];
- //获取平台信息
- ret = clGetPlatformInfo(platform[order], platform_info, ext_size, ext_data, NULL);
- //打印平台信息
- std::cout << ext_data << std::endl;
二、获取设备(Device):
设备是运行在平台上的可进行异构计算的单元,通常对应于同一平台的处理器。获取设备ID和信息的方法与函数同获取平台类似:
cl_int clGetDeviceIDs(cl_platform_id platform,
cl_device_type device_type,
cl_uint num_entries,
cl_device_id *devices,
cl_uint *num_devices)
第一个参数标识所要查询的平台,第二个参数用来保存查询到设备的类型,其余三个参数的含义与clGetPlatformIDs一致。
cl_int clGetDeviceInfo(cl_device_id device,
cl_device_info param_name,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret)
第一个参数标识所要查询设备,其余参数的含义与clGetPlatformInfo一致。
设备查询函数的使用和平台一样,一般通过两次调用来获得设备的个数和相应的信息,具体可以参考获取平台相关函数的使用方法。
三、建立上下文(Context):
上下文(Context)是将同一平台上不同架构的设备连接在一起的纽带,在同一个上下文的设备才可以进行通信、读写、共享内存等操作。程序运行时,使用上下文来管理命令队列、内存、内核等对象。建立上下文可以使用:
cl_context clCreateContext(cl_context_properties *properties,
cl_uint num_devices,
const cl_device_id *devices,
void *pfn_notify (const char *errinfo, const void *private_info, size_t cb, void *user_data),
void *user_data,
cl_int *errcode_ret)
该函数第一个参数指向一个列表,用来表明建立的上下文的属性及相对应的值;
第二个参数表明上下文中设备的个数;
第三个参数是指向设备ID的指针,用来标明建立上下文的设备;
第四个参数是一个回调函数,报告建立上下文中出现的错误;
第五个参数用来返回错误码,当上下文建立成功时返回0,即CL_SUCCESS。
如果建立上下文完成,该函数返回一个非0的上下文。
实际使用时根据之前获得的设备ID来建立上下文:
- cl_int ret; //用于保存函数返回值
- cl_context_properties context_props[]
- = { CL_CONTEXT_PLATFORM, (cl_context_properties)platform[1], 0 };; //设置上下文属性
- //
- //建立上下文
- cl_context context = clCreateContext(context_props, num_device, devices, NULL, NULL, &ret);
建立完上下文,就可以在其后进行建立命令队列、设置内核等操作。我们的OpenCL编程的万里长征也算是完成了第一步。
文章来源: blog.csdn.net,作者:网奇,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/jacke121/article/details/58058101
- 点赞
- 收藏
- 关注作者
评论(0)