【发布时间】:2011-05-09 22:18:31
【问题描述】:
如何在多 GPU 上实现基数排序 - 与在单 GPU 上的方式相同,即拆分数据,然后在单独的 GPU 上构建直方图,然后使用合并数据(如一堆卡片)?
【问题讨论】:
标签: concurrency parallel-processing cuda opencl gpu
如何在多 GPU 上实现基数排序 - 与在单 GPU 上的方式相同,即拆分数据,然后在单独的 GPU 上构建直方图,然后使用合并数据(如一堆卡片)?
【问题讨论】:
标签: concurrency parallel-processing cuda opencl gpu
该方法可行,但我认为这不是最快的方法。具体来说,合并每 K 位的直方图(K=4 目前最好)将需要在 GPU 之间交换密钥 32/K = 8 次以对 32 位整数进行排序。由于 GPU 之间的内存带宽 (~5GB/s) 远低于 GPU 上的内存带宽 (~150GB/s),这会影响性能。
更好的策略是将数据拆分为多个部分,在不同的 GPU 上对每个部分进行并行排序,然后在最后将这些部分合并一次。这种方法只需要一次 GPU 间传输(与上面的 8 相比),因此速度要快得多。
【讨论】:
很遗憾,这个问题没有充分提出。这取决于元素的大小、元素在内存中的起始位置以及您希望排序后的元素最终驻留的位置。
有时可以通过将元素存储在共享相同公共前缀的组中来压缩排序列表,或者您可以动态地唯一元素,将每个元素存储在排序列表中一次并具有关联的计数。例如,您可以将一个巨大的 32 位整数列表排序为 64K 个不同的 16 位值列表,从而将内存需求减少一半。
一般原则是,您希望尽可能少地传递数据,并且您的吞吐量几乎总是与与您的存储策略相关的带宽限制相对应。
如果您的数据集超过了快速内存的大小,您可能希望以合并过程结束,而不是像其他人已经回答的那样继续进行基数排序。
我刚刚进入 GPU 架构,我不明白上面的 K=4 评论。我从来没有见过这样一个小 K 会被证明是最佳的架构。
我怀疑合并直方图也是错误的方法。我可能会让元素在内存中分段而不是合并直方图。在 GPU 结构中管理中尺度分散/聚集列表有那么难吗?我当然希望不会。
最后,很难想象为什么要让多个 GPU 参与这项任务。假设您的卡有 2GB 内存和 60GB/s 写入带宽(这就是我的中档卡所显示的)。三遍基数排序(11 位直方图)需要 6GB 的写入带宽(可能是您的速率限制因素),或者大约 100 毫秒来对 2GB 的 32 位整数列表进行排序。太好了,它们已经分类了,现在呢?如果您需要在没有某种预处理或压缩的情况下将它们运送到其他任何地方,那么分拣时间将是小鱼。
无论如何,今天刚刚编译了我的第一个示例程序。还有很多东西要学。我的目标应用程序是排列密集型的,它与排序密切相关。我相信我将来会再次讨论这个问题。
【讨论】: