我开始为我的 OpenCL 内核做大量的 3D 工作以进行过滤。是否有将 2D 或 3D 子集从全局内存复制到本地或私有内存的最佳方法?
其用途可能是获取 3D 数据集并应用 3D 内核(或对 3D 内核占用的空间进行操作)。每个线程将查看一个像素,将像素周围的数据裁剪为 3 维,即内核大小(例如 1、3、5 等),将此数据子集复制到本地或私有内存,然后例如,计算数据子集的标准偏差。
最简单且效率最低的方法是蛮力:
__kernel void Filter_3D_StdDev(__global float *Data_3D_In,
int KernelSize){
//Note: KernelSize is always ODD
int k = get_global_id(0); //also z
int j = get_global_id(1); //also y
int i = get_global_id(2); //also x
//Convert 3D to 1D
int linear_coord = i + get_global_size(0)*j + get_global_size(0)*get_global_size(1)*k;
//private memory
float Subset[KernelSize*KernelSize*KernelSize];
int HalfKernel = (KernelSize - 1)/2; //compute the pixel radius
for(int z = -HalfKernel ; z < HalfKernel; z++){
for(int y = -HalfKernel ; y < HalfKernel; y++){
for(int x = -HalfKernel ; z < HalfKernel; x++){
int index = (i + x) + get_global_size(0)*(j + y) + \
get_global_size(0)*get_global_size(1)*(k + z);
Subset[x + HalfKernel + (y + HalfKernel)*KernelSize + (z + HalfKernel)*KernelSize*KernelSize] = Data_3D_In[index];
}
}
}
//Filter subset here
}
这是非常低效的,因为对全局内存进行了如此多的调用。有没有办法改善这一点?
我的第一个想法是使用vload
来减少循环次数,例如:
__kernel void Filter_3D_StdDev(__global float *Data_3D_In,
int KernelSize){
//Note: KernelSize is always ODD
int k = get_global_id(0); //also z
int j = get_global_id(1); //also y
int i = get_global_id(2); //also x
//Convert 3D to 1D
int linear_coord = i + get_global_size(0)*j + get_global_size(0)*get_global_size(1)*k;
//private memory
float Subset[KernelSize*KernelSize];
int HalfKernel = (KernelSize - 1)/2; //compute the pixel radius
for(int z = -HalfKernel ; z < HalfKernel; z++){
for(int y = -HalfKernel ; y < HalfKernel; y++){
//##TODO##
//Automatically determine which vload to use based on Kernel Size
//for now, use vload3
int index = (i + -HalfKernel) + get_global_size(0)*(j + y) + \
get_global_size(0)*get_global_size(1)*(k + z);
int subset_index = (z + HalfKernel)*KernelSize*KernelSize
float3 temp = vload3(index, Data_3D_In);
vstore3(temp, subset_index, Subset);
}
}
//Filter subset here
}
有没有更好的方法?
提前致谢!