MPI_Send和MPI_Recv开销

时间:2010-03-06 23:15:59

标签: c mpi

所以我试图弄清楚在C代码中使用MPI在处理器之间发送和接收信息的通信开销。

我需要在发送和接收中传递一个缓冲区,但我想做的就是计算在两个处理器之间进行n次通信需要多长时间。

这是我的整个代码:

main(int argc, char** argv){

int n;
int rank;
int time;
int i;
MPI_Status status;

MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if(rank == 0){
    n = atoi(argv[1]);
    printf("Size of data set = %d\n", n);
}

MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

for(i = 0; i < n; i++){
    if(rank == 0){
        MPI_Send(&n, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
    }

    else{
        MPI_Recv(&n, 1, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
    }
}

MPI_Barrier(MPI_COMM_WORLD);

time = clock();
printf("Time: %d\n", time);

MPI_Finalize();
}

我做了一些测试,我发现当我取出for循环时它按照我想要的方式工作。那么导致无限循环或seg错误的for循环有什么问题呢?

4 个答案:

答案 0 :(得分:1)

有两个问题:

1)代码中没有检查以确保它收到“数据集的大小”。如果在没有有效命令行选项的情况下启动代码,则会出现段错误或依赖于您的系统,以不可预测的方式进行。

2)发送和接收中的标记不匹配。标签必须匹配才能成功通信。如果没有匹配的标签,Recv将永远等待,直到找到匹配的发送。并发送等待,直到找到匹配的接收。

将MPI_COMM_WORLD旁边的接收中的1更改为0,代码将正常运行。

答案 1 :(得分:1)

以下是一个完整的程序,可以满足您的要求。有几个问题会妨碍原始版本的运行:

  1. 标签不匹配,这会导致程序停止。
  2. 没有检查MPI_COMM_WORLD是否包含2个MPI进程,这也会导致停顿。
  3. 如果命令行中没有参数,则可能会出现seg错误。我添加了n的默认值。
  4. 时间不会产生任何有用的东西,你必须在send / recv开始运行之前调用clock()。
  5. 祝你好运!

    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    #include <mpi.h>
    
    #define TAG_NUMBER 777     // just something
    #define DEFAULT_N 10000000 // takes ~3 seconds on my laptop
    
    
    int main(int argc, char **argv)
    {
      int i,n,rank,size,message=0;
      clock_t start = clock();
      MPI_Status status;
    
      MPI_Init(&argc, &argv);
      MPI_Comm_rank(MPI_COMM_WORLD, &rank);
      MPI_Comm_size(MPI_COMM_WORLD, &size);
    
      // This test assumes two processes in MPI_COMM_WORLD
      // ---------------------------------------------------------------------------
      if (size != 2) {
        if (rank == 0) { // only rank 0 prints
          printf("Please run with exactly 2 processes.\n");
        }
        MPI_Finalize();
        return 1;
      }
    
      // Collect from the command line the number of messages to send, default to
      // DEFAULT_N.
      // ---------------------------------------------------------------------------
      if (rank == 0) {
        if (argc > 1) {
          n = atoi(argv[1]);
        }
        else {
          n = DEFAULT_N;
        }
        printf("Number of messages to send = %d\n", n);
      }
    
      // Make sure everyone has the same n.
      MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
    
      // ---------------------------------------------------------------------------
      // Here we have ranks 1 and 2 exchange n messages via MPI_Send and MPI_Recv.
      // ---------------------------------------------------------------------------
      for (i=0; i<n; i++) {
        if (rank == 0) {
          MPI_Send(&message, 1, MPI_INT, 1, TAG_NUMBER, MPI_COMM_WORLD);
        }
        else{
          MPI_Recv(&message, 1, MPI_INT, 0, TAG_NUMBER, MPI_COMM_WORLD, &status);
        }
      }
    
      MPI_Barrier(MPI_COMM_WORLD); // not really necessary
      printf("rank %d: time = %f seconds\n", rank,
         (double)(clock() - start)/CLOCKS_PER_SEC);
    
      MPI_Finalize();
      return 0;
    }
    

答案 2 :(得分:0)

我相信代码会挂起,除非您使用了两个MPI进程。

答案 3 :(得分:-1)

您是否尝试过streams benchmark