多线程应用程序的最佳排序

时间:2011-03-21 07:40:57

标签: c++ multithreading sorting

今天在接受采访时,我有一个问题,询问你使用哪种多线程应用程序。天气是合并排序或快速排序。

5 个答案:

答案 0 :(得分:8)

您对多线程应用程序使用合并排序。

原因:

合并排序将问题分成单独的较小问题(较小的数组),然后合并它们。这可以在单独的线程中完成。

快速排序对单个数组进行数据透视排序,因此在线程之间更难有效地划分问题。

答案 1 :(得分:4)

每个分而治之算法都可以很容易地并行化。合并排序和快速排序都遵循可以并行运行的相同基本模式:

procedure DivideAndConquer(X)
  if X is a base case then
    Process base case X
    return

  Divide X into [Y0 … Yn[
  for Y ∈ [Y0 … Yn[ in parallel do
    DivideAndConquer(Y)

  Merge [Y0 … Yn[ back into X

他们的不同之处在于,在快速排序中,划分很困难,合并是微不足道的(没有操作)。在合并排序中,它是相反的:分割是微不足道的,合并是困难的。

如果您实现上述架构,则快速排序实际上更容易并行化,因为您可以忘记合并步骤。对于合并排序,您需要跟踪已完成的并行任务。这搞砸了负载平衡。

另一方面,如果你遵循上面的模式,你就会遇到一个问题:第一个分区和最后一个分区只使用一个处理器而所有其他处理器都是空闲的。因此,将这些操作并行化也是有意义的。在这里,我们看到并行化快速排序中的分区步骤比并行合并排序中的合并步骤要困难得多。

答案 2 :(得分:3)

合并排序似乎更容易并行化和分发......想一想,你将它分解成可以轻松划分和分发的干净子问题。但话说回来,快速排序也是如此。但是,我可能更喜欢使用合并排序,因为它可能更容易。

答案 3 :(得分:3)

假设一个体面的枢轴选择,它并没有那么不同。

子问题很难并行化;他们使用(大部分)不相交的内存而不需要同步,因此实际的差异在于瓶颈:快速排序的初始分区与合并排序中的最终合并。忽视并行化这些将导致许多核心或少数元素的加速不良(这比你想象的要快得多!)。

两种算法都可以高效并行化。有关实验结果和实施细节,请参阅this MCSTL paper。 MCSTL是现在GNU C ++ std-lib并行模式的基础。

并不是很清楚哪种算法在所有情况下都会表现更好,因为它取决于数据分布以及交换或比较是否较慢。

答案 4 :(得分:1)

我认为他们正在寻找合并排序作为答案,因为很容易看出如何在线程之间拆分。虽然另一条评论表明qsort也可以分成更小的问题。可能很多人可以分成更小的问题。

有一个不容忽视的关键方面。与其他线程通信需要花费大量时间。在创建线程之前,你要排序的数据集必须是巨大的,或者是非常昂贵的,并且在它们之间进行通信将比使用单个线程更好。

除此之外,无论如何,您都存在严重的虚假共享问题。由于CPU被迫在多个核之间共享和更新数据,因此使多个线程使用相同的数据可以(通信时间尽可能慢)。除非您的算法能够正确对齐数据,否则将其传递给各种线程会降低速度。