OpenCL カーネルのフィルタリングのために、3D で多くの作業を開始しています。2D または 3D サブセットをグローバル メモリからローカルまたはプライベート メモリにコピーする最適な方法はありますか?
これは、3D データセットを取得して 3D カーネルを適用する (または 3D カーネルが占めるスペースを操作する) ために使用できます。各スレッドは 1 つのピクセルを見て、カーネルのサイズ (1、3、5 など) である 3 次元でピクセルの周囲のデータをトリミングし、このデータのサブセットをローカルまたはプライベート メモリにコピーしてから、たとえば、データのサブセットの標準偏差を計算します。
最も簡単で最も効率の悪い方法は、力ずくで行うことです。
__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
}
もっと良い方法はありますか?
前もって感謝します!