OpenCL全局内存获取

OpenCL全局内存获取,opencl,gpgpu,Opencl,Gpgpu,我正在考虑修改我的GPU OpenCL内核以加快速度。问题是有很多全局内存没有合并,而获取实际上会降低性能。所以我计划将尽可能多的全局内存复制到本地,但我必须选择要复制的内容 现在我的问题是:多取小块内存比少取大块内存更有害吗 一般来说,越大的粪便越少效率越高。我不能在不查看代码的情况下给出具体建议,但请确保访问工作项中的连续块以启用“流”。将数据放入本地内存后,请执行任何换位或随机内存访问。您可以使用clGetDeviceInfo查找设备的缓存线大小。(,CL_DEVICE_GLOBAL_ME

我正在考虑修改我的GPU OpenCL内核以加快速度。问题是有很多全局内存没有合并,而获取实际上会降低性能。所以我计划将尽可能多的全局内存复制到本地,但我必须选择要复制的内容


现在我的问题是:多取小块内存比少取大块内存更有害吗

一般来说,越大的粪便越少效率越高。我不能在不查看代码的情况下给出具体建议,但请确保访问工作项中的连续块以启用“流”。将数据放入本地内存后,请执行任何换位或随机内存访问。

您可以使用clGetDeviceInfo查找设备的缓存线大小。(,CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE)在当今许多设备上,此值通常为16字节

小的读取可能会很麻烦,但是如果您是从同一缓存线读取,则应该不会有问题。简单的回答是:你需要把你的“小块”放在内存中靠得很近,以保持它的速度

下面我有两个函数来演示访问内存的两种方法——vectorAddFoo和vectorAddBar。第三个函数copySomeMemory(…)特别适用于您的问题。两个向量函数的工作项都会添加一部分被添加的向量,但使用不同的内存访问模式。vectorAddFoo使每个工作项处理一个向量元素块,从其在数组中的计算位置开始,并通过其工作负载向前移动。vectorAddBar让工作项从其gid开始,并在获取和添加下一个元素之前跳过gSize(=全局大小)元素

vectorAddBar将执行得更快,因为读取和写入会落在内存中的同一缓存线中。每4次浮点读取将落在同一缓存线上,并且仅从内存控制器执行一个操作。在阅读了本文中的a[]和b[]之后,所有四个工作项都将能够进行加法,并将它们的写操作排队到c[]


vectorAddFoo将保证读取和写入不在同一缓存线中(除了非常短的vectors~totalElements我无法正确理解您的问题,但如果您具有较大的全局访问权限,并且如果这些内容被重复使用,则使用本地内存

注:本地工作规模小,共享数据少,因此没有任何用处, 较大的本地工作大小较少的并行线程。因此您需要选择最好的一个

__kernel void  
vectorAddFoo(__global const float * a,  
          __global const float * b,  
          __global       float * c,
          __global const totalElements) 
{ 
  int gid = get_global_id(0); 
  int elementsPerWorkItem = totalElements/get_global_size(0);
  int start = elementsPerWorkItem * gid;

  for(int i=0;i<elementsPerWorkItem;i++){
    c[start+i] = a[start+i] + b[start+i]; 
  }
} 
__kernel void  
vectorAddBar(__global const float * a,  
          __global const float * b,  
          __global       float * c,
          __global const totalElements) 
{ 
  int gid = get_global_id(0); 
  int gSize = get_global_size(0);

  for(int i=gid;i<totalElements;i+=gSize){
    c[i] = a[i] + b[i]; 
  }
} 
__kernel void  
copySomeMemory(__global const int * src,
          __global const count,
          __global const position) 
{ 
  //copy 16kb of integers to local memory, starting at 'position'
  int start = position + get_local_id(0); 
  int lSize = get_local_size(0);
  __local dst[4096];
  for(int i=0;i<4096;i+=lSize ){
    dst[start+i] = src[start+i]; 
  }
  barrier(CLK_GLOBAL_MEM_FENCE);
  //use dst here...
}