【问题标题】:MPI_Send and MPI_Recv overheadMPI_Send 和 MPI_Recv 开销
【发布时间】:2011-01-24 13:34:53
【问题描述】:

所以我试图弄清楚在 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 循环时它可以按照我想要的方式工作。那么导致无限循环或段错误的for循环有什么问题?

【问题讨论】:

  • 我很惊讶即使没有循环也能正常工作。您的发送和接收调用使用不同的标签,因此接收不应返回。您正在运行多少个进程?另外,如果你要使用 MPI,你也应该使用它的定时器调用:MPI_Wtime()
  • 我要做的只是从节点 0 发送到节点 1 并在节点 1 接收。这是处理器之间通信开销的简单收集。
  • 下面有几个正确答案;我只想补充一点,如果您正在寻找这些时间,一组非常方便的工具是英特尔 MPI 基准,software.intel.com/en-us/articles/intel-mpi-benchmarks,其中包括 MPI“乒乓”时间。

标签: c mpi


【解决方案1】:

有两个问题:

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

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

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

【讨论】:

    【解决方案2】:

    下面是一个完整的程序,可以满足您的要求。有几个问题会阻止原始版本工作:

    1. 标签不匹配,这会导致程序停止。
    2. 没有检查 MPI_COMM_WORLD 是否正好包含 2 个 MPI 进程,这也会导致停顿。
    3. 如果命令行中没有参数,您可能会遇到段错误。我为n 添加了一个默认值。
    4. 计时不会产生任何有用的信息,您必须在发送/接收开始运行之前调用 clock()。

    祝你好运!

    #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;
    }
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 回答与问题无关。
      【解决方案4】:

      你试过streams benchmark吗?

      【讨论】:

      • STREAM 与这个问题完全无关。 STREAM 用于测量系统上的持续内存吞吐量。问题是关于 MPI。
      猜你喜欢
      • 2016-04-22
      • 2011-11-11
      • 2014-04-17
      • 2017-10-25
      • 2015-05-14
      • 1970-01-01
      • 1970-01-01
      • 2016-09-09
      • 2018-03-05
      相关资源
      最近更新 更多