繁体   English   中英

来自环形拓扑的全局最大值,而不是来自c ++中的MPI_REDUCE

[英]global maxima from ring topology, not from MPI_REDUCE in c++

我希望进行一次效率测试,以使用MPI查找全局最大值,一次使用环形拓扑,再一次使用MPI_REDUCE函数。 我已经在代码中执行了MPI_REDUCE,它可以正常工作,但是我想通过环传递产生相同的结果。

我的想法是对每个处理器的局部最大值进行数组处理,然后将这些最大值随环一起传递,最后输出全局最大值。

不幸的是,我意识到我无法定义一个单一的数组来容纳进程的最大值,相反,我最终制作了由4个进程生成的4个不同的数组。 然后,我开始传递从rank = 0处理器开始的array [0]值,而不是仅传递一个max,我必须传递4个不同的数组值,因为我生成了4个不同的数组。 更糟糕的是,即使付出了所有这些努力,我也没有像仅从一行MPI_REDUCE代码获得的那样获得全局最大值。 必须有一种方法可以从环形拓扑中获得全局最大值,而我只是使事情变得复杂。

该代码的主要部分如下:

int main(int argc, char **argv)
{        
    int rank, size;

    MPI_Init (&argc, &argv);      // initializes MPI
    MPI_Comm_rank (MPI_COMM_WORLD, &rank); // get current MPI-process ID. O, 1, ...
    MPI_Comm_size (MPI_COMM_WORLD, &size); // get the total number of processes    

    /* define how many integrals */
    const int n = 10;       

    double b[n] = {5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0,5.0};                    
    double a[n] = {-5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0,-5.0};  

    double result, mean;
    int m;

    const unsigned int N = 5;
    double max = 0;
    double max_store[4];

    cout.precision(6);
    cout.setf(ios::fixed | ios::showpoint); 

    srand(time(NULL) * rank);  // each MPI process gets a unique seed

    m = 4;                // initial number of intervals

    // convert command-line input to N = number of points
    //N = atoi( argv[1] );
    for (unsigned int  i=0; i <=N; i++)
    {
        result = int_mcnd(f, a, b, n, m);
        mean = result/(pow(10,10));

        m = m*4; 
        if( mean > max) 
        {
         max = mean;
        }
        if ( rank < 4 && rank >= 0 ) 
        {
         max_store[rank] = max;
        }            
    }

    //print the array containing max from each processor
    for( int k = 0; k < 4; k++ )
    {
     printf( "%1.5e\n", max_store[k]);
    }

    printf("Process ID %i, local_max = %f\n",rank, max);

    // All processes get the global max, stored in place of the local max
    MPI_Allreduce( MPI_IN_PLACE, &max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD );

    printf("Process ID %d, global_max = %f\n",rank, max);

    double send_junk = max_store[0];
    double rec_junk;
    //double global_max;
    MPI_Status status;

  if(rank==0) 
  {
    MPI_Send(&send_junk, 4, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD); //  send data to process 1
  }
  if(rank==1) 
  {
    MPI_Recv(&rec_junk, 4, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status); // receive data from process 0
  }
  //check between process 0 and process 1 maxima
  if(rec_junk>=max_store[1])
  {
   rec_junk = max_store[0];
  }
  else
  {
   rec_junk = max_store[1];
  }
  send_junk = rec_junk;

  MPI_Send(&send_junk, 4, MPI_DOUBLE, 2, 0, MPI_COMM_WORLD); //  send data to process 2

  if(rank==2)
  {
   MPI_Recv(&rec_junk, 4, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &status); // receive data from process 1
  }
  //check between process 1 and process 2 maxima
  if(rec_junk>=max_store[2])
  {
   rec_junk = rec_junk;
  }
  else
  {
   rec_junk = max_store[2];
  }
  send_junk = rec_junk;

  MPI_Send(&send_junk, 4, MPI_DOUBLE, 3, 0, MPI_COMM_WORLD); //  send data to process 3

  if(rank==3)
  {
   MPI_Recv(&rec_junk, 4, MPI_DOUBLE, 2, 0, MPI_COMM_WORLD, &status); // receive data from process 2
  }
  //check between process 2 and process 3 maxima 
  if(rec_junk>=max_store[3])
  {
   rec_junk = rec_junk;
  }
  else
  {
   rec_junk = max_store[3];
  }

  printf("global ring max = %f", rec_junk); 

  MPI_Finalize(); // programs should always perform a "graceful" shutdown
  return 0;
}

我有问题:

  1. 我可以轻松打印并查看进程ID和局部最大值,但是如何将局部最大值存储在单个数组中?

  2. 使用环形拓扑查找全局最大值的更有效方法是什么?

非常欢迎您的建议。 谢谢

要将所有进程的本地结果收集到单个数组中,请使用MPI_Gather如果您希望它们都在进程0中),或使用MPI_Allgather在每个进程中获取它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM