我遇到了在OpenCL中找到最大数组的简单任务的问题。
__kernel void ndft(/* lots of stuff*/)
{
size_t thread_id = get_global_id(0); // thread_id = [0 .. spectrum_size[
/* MATH MAGIC */
// Now I have float spectrum_abs[spectrum_size] and
// I want the maximum as well as the index holding the maximum
barrier();
// this is the old, sequential code:
if (*current_max_value < spectrum_abs[i])
{
*current_max_value = spectrum_abs[i];
*current_max_freq = i;
}
}
现在我可以添加if (thread_id == 0)
并像在单个核心系统上那样遍历整个事物,但是因为性能是一个关键问题(否则我不会这样做)在GPU上进行频谱计算,有更快的方法吗?
在上面内核的末尾返回CPU不是一个选项,因为内核实际上在此之后继续。
答案 0 :(得分:2)
您需要编写并行缩减。将“大”数组拆分成小块(单个工作组可以有效处理的大小)并计算每个数组的最小值。
迭代地执行此操作(包括主机和设备代码),直到您只剩下一组最小/最大值。
请注意,您可能需要编写一个单独的内核来执行此操作除非当前的工作分配适用于此内核(请参阅上面的问题)。
如果您当前的工作分配是可行的,则另一种方法是在每个工作组内找到最小最大值并将其写入全局内存中的缓冲区(index = local_id)。在barrier()之后,简单地让内核在thread_id == 0上运行,遍历简化结果并找到其中的最大值。这不是最佳解决方案,但可能适合您当前的内核。