我的应用程序在device-code
中执行了一些操作,并在kernel
内生成了一个数组。
我需要搜索此数组中第一次出现的元素。我怎样才能在GPU中执行它?如果我将数组复制到CPU并在那里工作,它将产生如此多的内存流量,因为这段代码被多次调用。
答案 0 :(得分:1)
最有可能是更复杂的解决方案,但是首先,特别是如果元素的出现次数非常少,那么简单的暴力原子能可能是一个可行的解决方案:
template<typename T> __global__ void find(T *data, T value, int *min_idx)
{
int idx = threadIdx.x + blockDim.x*blockIdx.x;
if(data[idx] == value)
atomicMin(min_idx, idx);
}
如果出现的次数确实很小,因此几乎所有线程甚至都没有尝试访问原子,这实际上可能并不是一个糟糕的解决方案。否则(如果搜索到的元素不是那么罕见),你会有更多的内部内部发散,更糟糕的是,原子操作发生冲突的概率要高得多。
编辑:对于更复杂的方法(但可能仍然不是最好的方法),否则您也可以在预步骤中创建一个int
数组,其值为索引{{1如果输入数组的元素等于该索引处的搜索元素,则设置为idx
,如果不匹配,则设置为idx
:
INT_MAX
然后对该索引数组执行“经典”最小约简以获得第一个匹配索引。
答案 1 :(得分:0)
一种方法是使用atomic
操作,阻止其他线程访问可编辑数据,直到当前正在处理的数据完成为止。
以下是查找单词首次出现的示例:
http://supercomputingblog.com/cuda/search-algorithm-with-cuda/
在该示例中使用atomicMin
函数。此外,文章中还有GPU和CPU之间的性能比较。
查找第一次出现的另一种方法是使用称为并行缩减的方法。 CUDA SDK中有一个并行求和的示例(该示例计算数组中所有值的总和)。并行缩减是一个很好的选择,特别是如果您使用具有较旧计算能力版本的硬件并且需要高精度。
要使用并行缩减查找第一次出现,首先要检查数组中的值是否等于您要查找的值。如果是,则保存其索引。然后,执行一个或多个min
操作(非原子最小值),您可以在其中比较上一步中保存的索引。您可以通过编辑CUDA SDK的并行总和示例来实现此搜索。
This site提供了有关缩减和原子操作的一些信息。它还包括我在这里没有谈到的二叉树缩减和变通原子函数。
还讨论了原子与减少问题on Stack Overflow。