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