【问题标题】:Quicksort, implementation on MPI快速排序,在 MPI 上的实现
【发布时间】:2022-01-17 15:14:36
【问题描述】:

我们有一个使用 MPI quicksort 实现的快速排序算法。有一个关于代码的问题,我们为什么要这样做

quicksort(chunk, 0, own_chunk_size);
 
  for(int step = 1; step < number_of_process; step = 2 * step)
  {
        if (rank_of_process % (2 * step) != 0) {
            MPI_Send(chunk, own_chunk_size, MPI_INT,
                     rank_of_process - step, 0,
                     MPI_COMM_WORLD);
            break;
        }
 
        if (rank_of_process + step < number_of_process) {
            int received_chunk_size
                = (number_of_elements
                   >= chunk_size
                          * (rank_of_process + 2 * step))
                      ? (chunk_size * step)
                      : (number_of_elements
                         - chunk_size
                               * (rank_of_process + step));
            int* chunk_received;
            chunk_received = (int*)malloc(
                received_chunk_size * sizeof(int));
            MPI_Recv(chunk_received, received_chunk_size,
                     MPI_INT, rank_of_process + step, 0,
                     MPI_COMM_WORLD, &status);
 
            data = merge(chunk, own_chunk_size,
                         chunk_received,
                         received_chunk_size);
 
            free(chunk);
            free(chunk_received);
            chunk = data;
            own_chunk_size
                = own_chunk_size + received_chunk_size;
        }
  }

问题出现在行中:

 if (rank_of_process % (2 * step) != 0)

if (rank_of_process + step < number_of_process)

为什么我们需要这些条件,它们有什么作用?据我了解,排序是使用块方法实现的(进程对其数据块进行排序)

【问题讨论】:

  • 只是好奇,第一句话的“我们”是谁?您似乎在询问有关您自己的代码的问题。

标签: mpi


【解决方案1】:

您的代码对每个进程进行本地快速排序。这是第一行,你称之为“块方法”。之后,您就有了合并的树形实现:首先与步骤 1 合并,即相邻进程,然后与步骤 2、步骤 4 等合并。本质上这是归并排序。

时间复杂度是长度为 n, 2n, 4n, .... N/2 的 log2(N) 步,其中 N 是元素的总数,n 是局部的,所以这本质上是 N。在极限情况下P=N(因此 n=1)这使得并行运行时间为 N,因此您对 Nlog(N) 的顺序复杂度的加速是 log(N)=log(P),这远非最优。

正确的并行快速排序(很难编码)将使用前缀操作进行初始红/白/蓝拆分,因此该步骤具有复杂度 log(N),(而不是本地合并的 N) ,所以并行快速排序有一个复杂度 log(N)-squared,提供了一个加速 P/log(P),这比您的合并排序之类的代码要好得多。

您的代码的问题在于您没有正确地思考分布式内存方面的问题:您从零进程上的所有内容开始,然后将其带回零进程。因此,您正在混合一个真正的分布式实现和一个管理器/工作者模型。这不是最佳并行,因此您获得的复杂性更接近于顺序而不是并行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-10
    • 2012-08-12
    • 2018-12-02
    • 2018-06-09
    相关资源
    最近更新 更多