【问题标题】:Sorting array with MPI in C++在 C++ 中使用 MPI 对数组进行排序
【发布时间】:2012-01-13 22:04:55
【问题描述】:

我想使用 MPI 库对随机数数组进行排序。这个想法是用 MPI_Scatterv 切割数组并将其发送到进程。每个进程都应该对它的数据量进行本地排序并将其发送回主进程(MPI_Gatherv)。主进程应该对部分排序的表进行排序(合并)。如果最后一步有问题。我只是无法正确合并表格。 有任何想法吗? 这是代码:

    #include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "math.h"
#include "mpi.h"
#include <time.h>


#define N 20

int numOfProc, idproc;


int compare(const void * a, const void * b) {
   const int *ia = (const int *)a;
    const int *ib = (const int *)b;
    return *ia  - *ib; 
}



int main(int argc,char ** argv) {

   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &numOfProc );
   MPI_Comm_rank(MPI_COMM_WORLD, &idproc);

   int * buf, * send_buf, * receive_buf, * sorted_buf, *displ, *sendcnts, *recvcnts;
   int count = N/numOfProc;
   int size, i;
   int temp, index;


   displ=(int*)malloc(numOfProc*sizeof(int));

   sendcnts=(int*)malloc(numOfProc*sizeof(int));

   recvcnts=(int*)malloc(numOfProc*sizeof(int));

   buf=(int*)malloc(count*sizeof(int));

   for(i=0; i<numOfProc; i++){
       displ[i]=i*count;
       sendcnts[i]=count;
       recvcnts[i]=count;
   }



   if(idproc == 0) {
      size=N;
      send_buf=(int*)malloc(size*sizeof(int));
      receive_buf=(int*)malloc(size*sizeof(int));


      for (i=0;i<size;i++) {
         send_buf[i] = rand();
      }
      printf("\n\n");
      fflush(stdout);
   }

   MPI_Scatterv(send_buf, sendcnts, displ, MPI_INT, buf, count, MPI_INT, 0, MPI_COMM_WORLD);

   printf("proces %d: ", idproc);
   qsort(buf, count, sizeof(int), compare);
   for (int i = 0; i < count; i++) printf("%d ", buf[i]);
   printf("\n\n");
   fflush(stdout);

   MPI_Gatherv(buf, count, MPI_INT, receive_buf, recvcnts, displ, MPI_INT, 0, MPI_COMM_WORLD);

   if (idproc == 0) {
       //merge
       temp=INT_MAX;
       for(i=0; i<size; i++){
           for(int j=0; j<numOfProc; j++){

               if(temp>receive_buf[displ[j]]){
                   temp=receive_buf[displ[j]];
                   receive_buf[displ[j]]=receive_buf[i];
                   receive_buf[i]=temp;
               }

           }

           printf("%d ", receive_buf[i]);
       }


      printf("\n");
      fflush(stdout);
   }
   wait(100);
   MPI_Finalize();
}

提前致谢,伊戈尔

【问题讨论】:

    标签: c++ mpi


    【解决方案1】:

    各个进程将对父数组的子集进行排序。但是在主进程收集所有这些子集之后,必须对父数组进行一次排序。

    例如

    原始数组 = {1,7,2,3, 10,4,8,0, 11,5,9,6}

    分散后进程 1:{1,7,2,3} 进程 2:{10,4,8,0} 进程 3:{11,5,9,6}

    和单个进程排序:{1,2,3,7},{0,4,8,10},{5,6,9,11}

    因此,收集后您的原始数组为 {1,2,3,7 , 0,4,8,10 , 5,6,9,11}

    因此必须再进行一次排序。

    编辑:

    其中一个解决方案是(这可以进一步优化): 而不是使用 mpi 分散和收集使用普通的 mpi 发送和 mpi 接收。 主进程/节点会将数据提供给虚拟主进程/节点,虚拟主进程/节点将进一步将其划分给其余节点。最后一行节点可以对数据子集进行排序,并将排序后的子集返回给它们的父节点。
    在父母收到单独排序的子集后,他们将对排序后的子集进行排序并将其集合提供给他们的父母。

    这种方法可以进一步优化。

    【讨论】:

    • 是的,我知道,但我不知道如何实现它。你能帮我解决这个问题吗?
    • 感谢您的所有努力,但我必须使用 sctterv 和 collectv 来完成我的作业。而且我必须对最终数组进行排序,就像我在代码中的“//merge”注释之后尝试做的那样。
    • 是的。在收集后进行最后一次排序也是可行的方法!。
    猜你喜欢
    • 2018-02-28
    • 2020-03-29
    • 1970-01-01
    • 2011-04-23
    • 2013-12-24
    • 2013-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多