【问题标题】:MPI QuickSort ProgramMPI 快速排序程序
【发布时间】:2016-03-27 15:54:04
【问题描述】:

我是新手,正在尝试编辑程序。我有一个 MPI 程序,将数组划分为子集,主机将子集发送给从机,它们进行快速排序,然后将排序后的数字返回给主机,以便他可以将它们写入文件中。 我想要做的是让快速排序发生得更快。我的想法是让主人划分数组并将子集发送给奴隶,但为自己保留一个。然后将它们再次划分为新的子集(例如,如果我们在数组中有从 1 到 100 的数字,则新子集应该是从 1 到 25、26 到 50、51 到 75 和 76 到 100),然后保留第一个子集( 1 到 25)为自己,将第二个(26 到 50)发送到第一个从站,将第三个(51 到 76)发送到第二个从站等。从站也应该这样做。然后它应该执行快速排序,并且从站应该将排序后的数字返回给主站。我希望这种方式应该更快。问题是,正如我所说,我是一个新手,我需要想法、建议甚至代码方面的帮助,这样我才能实现我的目标。

【问题讨论】:

  • 您真的要解决排序太慢的实际问题吗?然后忘记这种方法并阅读parallel sorting algorithms,更好地思考/询问如何首先保持数据分布。或者这是一个练习,您打算学习如何使用 MPI?
  • 这只是一个练习,所以我可以学习一些MPI。
  • 知道如何使从属设备将范围内的子阵列再分一次吗?例如,如果代码中的数字是从 0 到 100,我需要将它们分成 4 组(1 个主 + 3 个从属),范围为:0-25/26-50/51-75/76-100。

标签: c


【解决方案1】:

对于这个答案,我将坚持这样的假设,即应该使用快速排序来完成,并且数据是在单个进程中读取的。请记住,有many sophisticated parallel sorting techniques

您按子集分隔数字的想法是有问题的,因为它对数据的形状做出了假设。对于非均匀分布的数据集,知道最小值和最大值甚至都无济于事。最好简单地向每个进程发送相同数量的数字,让它们排序然后合并数据。

对于合并,您从 ntasks 排序的子列表开始,并希望以单个子列表结束。一个简单的合并会反复寻找每个子列表中的最小元素,将其删除并将其附加到最终列表中。这需要ntasks * N 比较、N 交换和N * 2 内存。您可以通过执行实际的合并排序来优化与log2(ntasks) * N 的比较,但这也需要log2(ntasks) * N 交换。您可以通过将子列表(或指向它们的第一个元素的指针)保留在 priority queue 中来进一步完善它,这应该会给您提供 log2(ntasks) * N 比较和 N 交换。

关于MPI的使用:

  1. 不要紧跟在后面使用MPI_IsendMPI_Wait。在这种情况下,请改用MPI_Send。仅当您实际上可以在 MPI_IsendMPI_Wait 之间做一些有用的事情时,才使用直接变体。
  2. 尽可能使用集体操作。要将数据从根分发到所有从站,请使用MPI_ScatterMPI_Scatterv。第一种要求所有rank都接收相同数量的元素,这也可以通过padding来实现。要从 master 中的 slave 收集数据,请使用 MPI_GatherMPI_Gatherv1 集合更容易正确,因为它们描述了高级操作。它们的实现通常是高度优化的。
  3. 要接收未知大小的消息,您也可以直接发送消息并在接收方使用MPI_Probe 来确定大小。如果您知道上限,您甚至可以使用比发送缓冲区更大的缓冲区MPI_Recv

1您还可以将合并步骤视为减少,并为此并行化必要的计算。

【讨论】:

  • 知道如何使从属设备将范围内的子阵列再分一次吗?例如,如果代码中的数字是从 0 到 100,我需要将它们分成 4 组(1 个主 + 3 个从属),范围为:0-25/26-50/51-75/76-100。
  • 恐怕我不太明白这个问题。划分本身相当容易:rank = (value - min) * num_ranks / (1 + max - min).
  • 现在主机正在分割数组并将子数组发送给从机,为自己保留一个。我不知道该怎么做是让从机对他得到的子数组进行另一次划分,但它需要在某些范围内完成,具体取决于打开文件中数字的范围。如果从站收到数字 1,27,33,45,50,71,23,5,99,88 它应该将它们分组为 (1,23,5),(27,33,45,50), ( 71)和(99,88)。所有从站和主站都应该这样做,然后第一组应该发送到主站,第二组应该发送到第一个从站等等。
  • 为什么第二个分区会比第一个分区不同/更难?你为什么要这样做?
  • 所以主人和奴隶应该有一个范围内的数字,他们可以更快地排序,然后当我将它们发送回主人时,他会得到它们已经排序并且不需要排序。跨度>
【解决方案2】:

原则上,您的解决方案看起来非常好。我不完全理解您是否打算将较大的文件分块或整体处理。根据我的经验,我建议您为从站分配尽可能大的块。这样,相当昂贵的消息传递操作很少执行。

我在您的问题中无法理解的是您计划的总体目标是什么。您是否打算并行排序完整的输入文件?如果是这种情况,您将需要对从各个流程收到的结果应用某种合并排序。

【讨论】:

  • 知道如何使从属设备将范围内的子阵列再分一次吗?例如,如果代码中的数字是从 0 到 100,我需要将它们分成 4 组(1 个主 + 3 个从属),范围为:0-25/26-50/51-75/76-100。