快速分类排序:我做得对吗?

时间:2011-07-29 19:13:15

标签: sorting cuda gpgpu

我正在研究不同的排序算法,并且当我得到这种排序的想法而没有实际排序时,试图考虑如何将它们移植到GPU。这就是我内核的样子:

__global__ void noSort(int *inarr, char *outarr, int size)
{
    int idx = threadIdx.x + blockIdx.x * blockDim.x;
    if (idx < size) 
            outarr[inarr[idx]] = 1;
}

然后在主机端,我只是打印outarr[i] == 1的数组索引。现在有效地,上面可以用来对整数列表进行排序,这也可能比实际排序的算法更快。

这是合法的吗?

2 个答案:

答案 0 :(得分:2)

对于具有唯一键的输入(即没有重复项),您的示例本质上是一个专门的counting sort。要使代码成为正确的计数排序,您可以将outarr[inarr[idx]] = 1替换为atomicAdd(inarr + idx, 1),以便计算重复的键。但是,除了原子操作相当昂贵的事实之外,您仍然存在方法的复杂性与输入中的最大值成比例的问题。幸运的是,radix sort解决了这两个问题。

基数排序可以被认为是计数排序的一般化,它一次只查看输入的B位。由于B位的整数只能采用[0,2^B)范围内的值,因此我们可以避免查看整个值范围。

现在,在你对CUDA实施基数排序之前,我应该警告你已经studied extensivelyextremely fast实现了。实际上,Thrust库会尽可能自动应用基数排序。

答案 1 :(得分:1)

我看到你在这里做了什么,但我认为它只适用于特殊情况。例如,如果inarr元素的值非常大,该怎么办?这将需要outarr至少具有尽可能多的元素才能处理它。重复数字怎么样?

假设您开始使用其中包含唯一的小值的数组,这是一种有趣的排序方式。总的来说,在我看来,它会使用大量的内存来做一些已经通过并行合并排序等算法很好地处理的东西。读取输出数组也是一个非常昂贵的过程(特别是如果输入数组中有任何大的值),因为你最终会得到一个非常稀疏的数组。