Memory OpenCL:使用什么类型的内存?

Memory OpenCL:使用什么类型的内存?,memory,constants,local,opencl,Memory,Constants,Local,Opencl,我有一些过滤内核,类似这样: __kernel void filterKernel (__global float4 *filter, __global float4* in_array, __global float4* out_array) { ... out_array[tid] = in_array[tid] * filter[fid]; ... } 内核过滤器内核被调用多次(大约1000次) 变量过滤器是一个浮动数组,从不更改其值(对于所有工作组和所有内核调用保持不变) in_数组

我有一些过滤内核,类似这样:

__kernel void filterKernel (__global float4 *filter, __global float4* in_array, __global float4* out_array)
{
...
out_array[tid] = in_array[tid] * filter[fid];
...
}
  • 内核过滤器内核被调用多次(大约1000次)

  • 变量过滤器是一个浮动数组,从不更改其值(对于所有工作组和所有内核调用保持不变)

  • in_数组包含32768个浮点数


这个变量过滤器的最佳声明是什么__恒定的__地方的也许在这里和那里放一个“const”?什么对编译器最有帮助?什么使代码最快?

您应该使用常量地址空间(“常量”),因为大多数GPU都有用于常量内存的特殊缓存。唯一的问题是常量内存的大小很小(大约为16-64KBs)。

如果不是太大,请尝试在.cl文件中全局定义筛选器。
您可以尝试在\uu常量\uu本地空间中分配它,并比较哪个更快。但并非所有SDK都支持本地地址空间中的全局变量(我正在看ATI)


如果您仍然想将筛选器作为内核参数传递,请考虑调用它的SETKENELARG(0,…),仅<强>曾经< /强>。只要内核参数的值或索引不变,就不必调用SetKernelArg()1000次。虽然这可能不会对性能产生可测量的影响,但它仍然更干净。

\u local可能是错误的,因为您无法将其初始化为任何内容。如果使用常量内存,您可能希望使用_u常量,只要它合适。

如果我使用常量内存:我应该在.cl文件中添加一个define(例如_u常量float4*filter={1.0,2.0,3.0,…};),还是在调用函数之前在函数接口中保留filter并填充CPU上的数组?有什么区别吗?@Frizz:使用clSetKernelArg从CPU填充。这比填充.cl文件中的_常量数组慢得多。请参阅下面我的评论。从我迄今为止尝试过的各种方法(常量内存、LDS、纹理缓存)中,在.cl文件中将其定义为_常量是迄今为止(!)最快的。令人惊讶的是,a)在调用前通过SetkernelArg()将_常量数组传递给内核,或者B)在.cl文件本身中定义_常量数组,两者之间存在巨大的(!)差异。不幸的是,方法B)仅适用于ATI/AMD。Nvidia的OpenCL实现在这里有缺陷(我已经报告了这个缺陷,将在CUDA3.3中修复)。CUDA SDK有很多缺陷。我尝试在内核中使用位移位操作实现byte_swap()函数。OpenCL编译器识别函数的用途,并尝试将其映射到bswap32 resp。bswap64指令-找不到或无法解析…Frizz:您是否检查过只为_常量缓冲区设置一次内核参数与在每个内核排队之前设置一次的影响?不,我没有检查这是否有区别。可以。。。通常我只测试ClenqueEndRange()调用完成所需的时间。选中:这一点没有任何区别(只设置一次_常量缓冲区内核参数,而不是每次内核调用之前)。至少在我的硬件(GT240)上没有。您的问题得到回答了吗?如果是,请接受回答。