【OpenCL编程任务一】输出进行运算设备的名称
来源:互联网 发布:安德罗妮淘宝 编辑:程序博客网 时间:2024/05/16 08:30
前言
最近在学习OpenCL,想通过一些实例,进行快速入门与上手。
任务描述
输出进行运算设备的名称。
思路
1、具体细化这个任务。我们肯定首先要获取到这个设备的ID或是(地址),然后将其转换为OpenCL可用于输出的格式,将其输出。首先使用clGetPlatformIDs函数,这个命令会得到可用的OpenCL平台的列表。如果参数platforms为NULL,clGetPlatformIDs会返回可用平台数。返回的平台数可以用num_entries来限制,这个参数要大于0并小于或等于可用平台数。
GetPlatformIDs(cl_uint /* num_entries */, cl_platform_id * /* platforms */, cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
我们可以这么用,这个时候num其实得到了平台数。err用于判断是否成功执行了,如果成功会返回CL_SUCCESS:
cl_int err; cl_uint num; err = clGetPlatformIDs(0, 0, &num); if (err != CL_SUCCESS) { std::cerr << "Unable to get platforms\n"; return 0; }
2、得到了平台数还不够,我们要获得ID。这个时候再次用这个clGetPlatformIDs函数,只要platform不设置成NULL,那么就可以得到ID了对不对?下面的代码中,ID被存放在了vector容器中。
std::vector<cl_platform_id> platforms(num); err = clGetPlatformIDs(num, &platforms[0], &num); if (err != CL_SUCCESS) { std::cerr << "Unable to get platform ID\n"; return 0; }
3、得到了ID,我们要想办法输出。(这个地方我也没太懂)引用一下:在OpenCL中,是透过一个property的阵列,以「property种类」及「property内容」成对出现,并以0做为结束。所以,要先建立一个阵列(数组),然后由于要指定的property是cl_context_platform,但是刚刚取得的(看上面)
是cl_platform_id对不对(即platforms[0])?所以要用一个C++的强制转换符reinterpret_cast来进行转换。它的使用形式大概如下:
reinterpret_cast<目标格式>(数据)
回到上文。我们转换数据后,要将其转换为阵列(数组),所以命名一个cl_context_properties的阵列,最后一项是0,第一项,种类,也就是CL_CONTEXT_PLATFORM,第二项,内容,即转换后的数据:
cl_context_properties prop[] = { CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(platforms[0]), 0 };
4、有了阵列,我们就可以建立一个context来准备输出了。用clCreateContextFromType这个函数,其定义如下:第一个参数,就是我们建立好的阵列;第二个参数,采用什么设置进行运算。
clCreateContextFromType(const cl_context_properties * /* properties */, cl_device_type /* device_type */, void (CL_CALLBACK * /* pfn_notify*/ )(const char *, const void *, size_t, void *), void * /* user_data */, cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
第三个参数是一个回调函数,用于传递错误信息。这个回调函数将由OpenCL实现用于报告在这方面出现的错误信息,可以由OpenCL实现异步调用,以确保回调函数是线程安全的。如果pfn_notify是空的,就没有注册回调函数。
第四个参数是当第三个参数被定义(注册)时才用到的,用于传递数据。如果上面为NULL,那么这里也为NULL。
第五个参数,返回一个合适的错误代码。如果errcode_ret是无效的,那么不返回错误代码。
所以,我们这么来定义:
cl_context context = clCreateContextFromType(prop, CL_DEVICE_TYPE_DEFAULT, NULL, NULL, NULL); if (context == 0) { std::cerr << "Can't create OpenCL context\n"; return 0; }
采用默认计算装置,还有几种可以选,包括:
CL_DEVICE_TYPE_CPU:使用CPU 装置
CL_DEVICE_TYPE_GPU:使用显示晶片装置
CL_DEVICE_TYPE_ACCELERATOR:特定的OpenCL 加速装置,例如CELL
CL_DEVICE_TYPE_DEFAULT:系统预设的OpenCL 装置
CL_DEVICE_TYPE_ALL:所有系统中的OpenCL 装置
4、我们得到了一个context,但是它可以包含一个或者多个装置。所以接下来的工作就是获得要取得装置的列表。使用clGetContextInfo函数。
clGetContextInfo(cl_context /* context */, cl_context_info /* param_name */, size_t /* param_value_size */, void * /* param_value */, size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &cb);
如上来使用,这个函数相对而言较为简单,它和第一个函数clGetPlatformIDs有点类似,调用两次,第一次取得列表的字节量保存在 size_t cb中。
接着我们想知道到底有几个装置?其实数学公式就是cb/id的固定字节数。那么第二次调用这个函数,获取所有device的列表。
clGetContextInfo(context, CL_CONTEXT_DEVICES, cb, &devices[0], 0);
5、将其转换为字符串,输出,可以使用
clGetDeviceInfo(cl_device_id /* device */, cl_device_info /* param_name */, size_t /* param_value_size */, void * /* param_value */, size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
当size_t 不为0时,这个函数将会把第四个参数所指的地方指向device的CL_DEVICE_NAME所在地址。如果我们把一个string类型的变量进行操作,那么就可以使用cout进行输出。(char*自然也可以)
最终程序
#include <iostream> #include <string> #include <vector> #include <OpenCL/opencl.h> #include <CL/cl.h> int main() { cl_int err; cl_uint num; err = clGetPlatformIDs(0, 0, &num); if (err != CL_SUCCESS) { std::cerr << "Unable to get platforms\n"; return 0; } std::vector<cl_platform_id> platforms(num); err = clGetPlatformIDs(num, &platforms[0], &num); if (err != CL_SUCCESS) { std::cerr << "Unable to get platform ID\n"; return 0; } cl_context_properties prop[] = { CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(platforms[0]), 0 }; cl_context context = clCreateContextFromType(prop, CL_DEVICE_TYPE_DEFAULT, NULL, NULL, NULL); if (context == 0) { std::cerr << "Can't create OpenCL context\n"; return 0; } size_t cb; clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &cb); std::vector<cl_device_id> devices(cb / sizeof(cl_device_id)); clGetContextInfo(context, CL_CONTEXT_DEVICES, cb, &devices[0], 0); clGetDeviceInfo(devices[0], CL_DEVICE_NAME, 0, NULL, &cb); std::string devname; devname.resize(cb); clGetDeviceInfo(devices[0], CL_DEVICE_NAME, cb, &devname[0], 0); std::cout << "Device: " << devname.c_str() << "\n"; clReleaseContext(context); std::cin.get(); return 0; }
感想
第一个感想,OpenCL存在着大量的套路操作:先呼叫某个函数,获取空间大小,把自己的资源进行调整后,第二次呼叫,取得想要的数据。第二个感想,OpenCL真尼玛麻烦…
- 【OpenCL编程任务一】输出进行运算设备的名称
- 【OpenCL编程任务二】将图片进行灰度化处理
- OpenCL编程入门(一)
- OpenCL编程的过程
- 安卓下使用OpenCL进行PowerVR GPU编程
- 第九周 C++任务一。定义Complex类中的<<和>>运算符的重载,实现输入和输出
- 第九周任务一(定义Complex类中的<<和>>运算符的重载,实现输入和输出)
- C++第九周【任务一】定义Complex类中的<<和>>运算符的重载,实现输入和输出
- OpenCL编程步骤(一):创建上下文
- 并行运算框架OpenCL的一些基本概念
- 使用 OpenCL.Net 进行 C# GPU 并行编程
- 第八周任务一:运算符的重载
- 第九周任务一 复数 输入输出运算符的重载
- 第八周任务-项目一(任务一成员函数的运算符重载)
- GDI(图形设备接口)编程(一)设备环境的获取
- Linux 里面的设备名称
- 固定磁盘设备的名称
- CUDA与OpenCL编程框架的比较
- Android四大组件之BroadcastReceiver
- 文章标题
- xUtils系列之BitmapUtils
- 收藏的几个链接
- Verilog 编程实验(6)-4位移位寄存器的设计与实现
- 【OpenCL编程任务一】输出进行运算设备的名称
- JDBC QueryRunner(开源框架)之查询 详解
- 143.Sort Colors II-排颜色 II(中等题)
- Java中类与类的关系
- JavaScript的任意拖拽改变盒子的宽高<案例>
- 51Nod-1406-与查询
- Jsp入门<1>Jsp入门基础简介与工作原理详解
- 微信小程序学习(5)_事件
- 第一次写博客