我正在实现此处所述的拆分操作:http://http.developer.nvidia.com/GPUGems3/gpugems3_ch39.html。目前我正在尝试实现分散步骤。
scatter 只是执行类似于OpenCL的shuffle操作的操作(此处为:https://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/shuffle.html),但是在一般工作组(__local)数组上而不是向量。
我试图在OpenCL文档中找到对此操作的支持,但没有运气。
是否有本机OpenCL支持此操作,如果没有,是否有一些文章或文章,我可以找到一个有效的算法来实现此操作?
可能有用的注释,我正在使用AMD的实现,所以如果有专门提供的解决方案,那就没关系了。但是,一般的解决方案要好得多。
以下是我在代码中尝试完成的内容。这是一个OpenCL函数,稍后将由另一个实现基数排序的内核调用:
void Split(__local uint local_keys[256], uint cur_bit, int local_id)
{
__local uint e[256];
__local uint f[256];
__local uint t[256];
__local uint d[256];
e[local_id] = !(local_keys[local_id] & (1 << cur_bit));
f[local_id] = work_group_scan_exclusive_add(e[local_id]);
work_group_barrier(CLK_LOCAL_MEM_FENCE);
uint total_falses = e[255] + f[255];
t[local_id] = local_id - f[local_id] + total_falses;
d[local_id] = e[local_id] ? f[local_id] : t[local_id];
work_group_barrier(CLK_LOCAL_MEM_FENCE);
// TODO scatter .... (Please see last step of the attached image)
.......
}
答案 0 :(得分:1)
在我看来,唯一的解决方案是使用辅助数组。像你指出的那样的特殊指令仅对可以保存在寄存器中的数组有效。当您跨越本地内存边界时它们无效,因为它需要工作项同步。
在您的过程中,您使用4个局部uint向量。这意味着您需要同时分配的本地内存量。因此,分配一个辅助数组来进行混洗不应该使用比你目前使用的内存更多的内存。
注意:编译器会在你得到计算值d后意识到e,f,t的范围就会消失。因此临时数组不应该使用额外的内存,因为它可以重用以前的内存。您还可以使用{ }
。
void Split(__local uint local_keys[256], uint cur_bit, int local_id)
{
__local uint e[256];
__local uint f[256];
__local uint t[256];
__local uint d[256];
__local uint temp[256];
e[local_id] = !(local_keys[local_id] & (1 << cur_bit));
f[local_id] = work_group_scan_exclusive_add(e[local_id]);
work_group_barrier(CLK_LOCAL_MEM_FENCE);
uint total_falses = e[255] + f[255];
t[local_id] = local_id - f[local_id] + total_falses;
d[local_id] = e[local_id] ? f[local_id] : t[local_id];
temp[local_id] = local_keys[local_id];
work_group_barrier(CLK_LOCAL_MEM_FENCE);
local_keys[d[local_id]] = temp[local_id];
}