opencl::kernel中获取local memory size
2016-03-04 15:22
561 查看
在OpenCL设备中一个workgroup中的所有work-item可以共用本地内存(local memory),在OpenCL kernal编程中,合理的利用local memory,可以提升系统的整体效率。
但是,根据OpenCL的标准,不论在kernel代码的编译期还是运行时,kernel程序在不借助主机端程序的帮助下,是无法知道当前设备(device)的local memory容量的。也就是说,不论是local memory的容量还是其他类型的设备信息,都必须由主机端程序在编译期或运行时告诉kernel。
我们知道,主机程序可以通过clGetDeviceInfo(点击打开函数说明)函数获取local memory size。
那么问题来了:主机如何告诉kernel这些信息?
都可以提供编译选项,而编译选项中的-D 参数允许定义宏。可以通过这个途径,将local memory size定义成一个常量提供给kernel代码。
下面是OpenCL编译器选项的部分说明,参见clBuildProgram函数说明
以下是我的C++代码片段
上面代码中add_define模板函数的实现
下面是kernel代码:
下面是主机端代码:
第二种办法因为在kernel运行时才确定local memory size,所以它的优点是一个设备的kernel代码可以不需要重新编译,就能在另一台设备上运行。
但是,根据OpenCL的标准,不论在kernel代码的编译期还是运行时,kernel程序在不借助主机端程序的帮助下,是无法知道当前设备(device)的local memory容量的。也就是说,不论是local memory的容量还是其他类型的设备信息,都必须由主机端程序在编译期或运行时告诉kernel。
我们知道,主机程序可以通过clGetDeviceInfo(点击打开函数说明)函数获取local memory size。
那么问题来了:主机如何告诉kernel这些信息?
编译期 -D name=value
在编译kernel的时候,不论你是用clBuildProgram还是用clCompileProgram+clLinkProgram都可以提供编译选项,而编译选项中的-D 参数允许定义宏。可以通过这个途径,将local memory size定义成一个常量提供给kernel代码。
下面是OpenCL编译器选项的部分说明,参见clBuildProgram函数说明
Compiler Options The compiler options are categorized as pre-processor options, options for math intrinsics, options that control optimization and miscellaneous options. This specification defines a standard set of options that must be supported by the OpenCL C compiler when building program executables online or offline. These may be extended by a set of vendor- or platform specific options. Preprocessor Options These options control the OpenCL C preprocessor which is run on each program source before actual compilation. -D options are processed in the order they are given in the options argument to clBuildProgram or or clCompileProgram. -D name Predefine name as a macro, with definition 1. -D name=definition The contents of definition are tokenized and processed as if they appeared during translation phase three in a `#define' directive. In particular, the definition will be truncated by embedded newline characters. -I dir Add the directory dir to the list of directories to be searched for header files.
以下是我的C++代码片段
// 当OpenCL设备只有1个时,定义CL_DEVICE_LOCAL_MEM_SIZE if (1 == _devices.size()) { // 如果设备不支持local memory,抛出异常 throw_if(CL_NONE == _devices[0].getInfo<CL_DEVICE_LOCAL_MEM_TYPE>(), _devices[0].getInfo<CL_DEVICE_NAME>().append("not support local memory")) // 获取设备的local memory size auto local_mem_size=_devices[0].getInfo<CL_DEVICE_LOCAL_MEM_SIZE>(); // 在编译选项中加入 -D CL_DEVICE_LOCAL_MEM_SIZE=%local_mem_size% add_define("CL_DEVICE_LOCAL_MEM_SIZE", local_mem_size); }
上面代码中add_define模板函数的实现
template<typename T> builder &add_define(const std::string &def,const T &v){ throw_if(def.empty(),"def is empty") std::stringstream stream; stream<<def<<"="<<v; _compiler_options+="-D "+stream.str()+" "; return *this; }
运行时clSetKernelArg
如果要在kernel运行时,告诉kernel local memory size,就要在kernel代码中增加参数下面是kernel代码:
__kernel void local_test(__local char*p,int local_size){ for(int i=0;i<local_size;++i){ p[i]=i; } }
下面是主机端代码:
cl_int local_mem_size; ..... //调用clGetDeviceInfo获取local memory size赋值给local_mem_size //设置kernel的第一个参数, //因为local_test的参数p定义为__local,所以不需要指定参数地址, //opencl设备会根据第三个参数的值分配相应字节数的local memory. //所以clSetKernelArg中最后一个参数只需要填NULL clSetKernelArg(kernel,0,local_mem_size,NULL); //设置kernel的第二个参数,告诉kernel 数组p的长度 clSetKernelArg(kernel,1,size(local_mem_size),&local_mem_size); ....//调用 clEnqueueNDRangeKernel执行kernel
总结
以上两种办法,各有优劣,所以具体使用哪种方法更合适,这真的根据你的需要,就我个人而言我采用第一种方法,因为第一种办法,直接在编译期就可以根据local memory大小来分配数组大小,这样以来kernel代码不需要带过多参数,代码维护性好一点点。第二种办法因为在kernel运行时才确定local memory size,所以它的优点是一个设备的kernel代码可以不需要重新编译,就能在另一台设备上运行。
相关文章推荐
- 神器SystemTap
- vbs Size 属性使用介绍(获取文件大小)
- mysql Out of memory (Needed 16777224 bytes)的错误解决
- MySQL Memory 存储引擎浅析
- PHP错误Allowed memory size of 67108864 bytes exhausted的3种解决办法
- MySQL错误ERROR 2002 (HY000): Can't connect to local MySQL server through socket
- 解决File size limit exceeded 错误的方法
- Git使用小坑 Out of memory错误的解决方法
- mysqld-nt: Out of memory (Needed 1677720 bytes)解决方法
- 解读Linux安全机制之栈溢出保护
- 簡單設定 kernel 選項在使用 iptables 前
- Ubuntu12.04内核升级出了问题
- linux系统调优-Cgroups
- [Linux学习笔记] Linux系统引导流程(一)
- 利用系统缓存提高PostgreSQL操作效率
- 用SQL命令查看 MySQL l数据库大小
- 更新Debian内核e1000e驱动模块
- 将centos7打造成桌面系统
- kernel: printk: 2 messages suppressed.
- win7(amd显卡) 安装 pyopencl