GPU上的并行冒泡排序

时间:2011-03-15 07:10:08

标签: sorting cuda bubble-sort

我正在使用CUDA实现简单的冒泡排序算法,我有一个问题 我执行以下代码,以交换数组中的2个连续元素:

if(a[threadIdx.x]>a[threadIdx.x + 1])
    Swap(a[threadIdx.x] , a[threadIdx.x + 1]);

请注意,块中的线程数是数组大小的一半。这是一个很好的实现吗?即使有分支,单个warp中的线程是否会并行执行?因此它实际上需要N次迭代才能对数组进行排序?

还要注意我知道我可以实现更好的排序算法,我可以使用Thrust,CUDPP或SDK中的样本排序算法,但在我的情况下,我只需要一个简单的算法来实现。

2 个答案:

答案 0 :(得分:2)

我假设:

  1. 您要排序的数组很小(<100个元素)
  2. 它是一些更大的GPU算法的一部分
  3. 数组位于共享内存空间中,或者可以在那里复制
  4. 如果其中任何一个不成立,请不要进行冒泡排序!

    块中的线程数是数组大小的一半。这是一个很好的实现吗?

    这是合理的。当在warp中出现发散分支时,所有线程都以完美同步的方式执行所有分支,只需要一些线程将其标记设置为“disabled”。这样,每个分支只执行一次。唯一的例外 - 当没有来自warp的线程占用分支时 - 那么只是跳过分支。

    BUG!

    在您的代码中,我看到了一个问题。如果您希望一个线程对数组的两个元素进行操作,请让它们专门处理它,即:

    if(a[2*threadIdx.x]>a[2*threadIdx.x + 1])
        Swap(a[2*threadIdx.x] , a[2*threadIdx.x + 1]);
    

    否则,如果Swap由两个相邻线程执行,则某些值可能会消失,而其他一些值可能会在数组中重复。

    另一个错误!

    如果您的块大于经线尺寸,请记得在需要时放置__syncthreads()。即使您的块较小(不应该),您应该检查__threadfence_block()以确保对同一块的其他线程可以看到对共享内存的写入。否则,编译器可能在优化方面过于激进并使您的代码无效。

    另一个问题

    如果您修复了第一个错误,您的共享内存将出现双向存储库冲突。它不是非常重要,但您可能希望重新组织数组中的数据以避免它们,例如按以下顺序包含连续元素:

    [1,3,5,7,9,...,29,31,2,4,6,8 ......,30,32]

    这样,元素1和2属于共享内存中的同一个库。

答案 1 :(得分:1)

我很高兴你意识到GPU上的冒泡排序可能会非常糟糕!我正在努力弄清楚如何获得足够的并行性而无需启动许多内核。此外,当你完成后,你可能很难解决问题。

无论如何,要回答你的具体问题:是的,在这种情况下你很可能会出现扭曲分歧。但是,鉴于“else”分支实际上是空的,这不会减慢你的速度。平均而言(直到此列表被排序),warp中大约一半的线程将采用“if”分支,其他线程将等待,然后当“if”分支完成时,warp线程可以恢复为脚背。这远非您最大的问题:)