MPI广播很慢

时间:2014-10-25 00:38:11

标签: mpi

我正在编写一个MPI程序,并且我正在使用的一台特定机器上的MPI_Bcast功能非常慢。为了缩小问题范围,我有以下两个测试程序。第一个执行从进程0到其他操作的许多MPI_Send / MPI_Recv操作:

#include <stdlib.h>
#include <stdio.h>
#include <mpi.h>

#define N 1000000000

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

  /* initialize MPI */
  MPI_Init(&argc, &argv);

  /* get the rank (process id) and size (number of processes) */
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);

  /* have process 0 do many sends */
  if (rank == 0) {
    int i, j;
    for (i = 0; i < N; i++) {
      for (j = 1; j < size; j++) {
        if (MPI_Send(&i, 1, MPI_INT, j, 0, MPI_COMM_WORLD) != MPI_SUCCESS) {
          printf("Error!\n");
          exit(0);
        }   
      }   
    }   
  }   

  /* have the rest receive that many values */
  else {
    int i;
    for (i = 0; i < N; i++) {
      int value;
      if (MPI_Recv(&value, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE) != MPI_SUCCESS) {
        printf("Error!\n");
        exit(0);
      }   
    }   
  }   

  /* quit MPI */
  MPI_Finalize( );
  return 0;
}

该程序仅需2.7秒左右即可运行4个进程。

下一个程序完全相同,只是它使用MPI_Bcast将进程0中的值发送到其他进程:

#include <stdlib.h>
#include <stdio.h>
#include <mpi.h>

#define N 1000000000

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

  /* initialize MPI */
  MPI_Init(&argc, &argv);

  /* get the rank (process id) and size (number of processes) */
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);

  /* have process 0 do many sends */
  if (rank == 0) {
    int i, j;
    for (i = 0; i < N; i++) {
      if (MPI_Bcast(&i, 1, MPI_INT, 0, MPI_COMM_WORLD) != MPI_SUCCESS) {
        printf("FAIL\n");
        exit(0);
      }   
    }   
  }   

  /* have the rest receive that many values */
  else {
    int i;
    for (i = 0; i < N; i++) {
      if (MPI_Bcast(&i, 1, MPI_INT, 0, MPI_COMM_WORLD) != MPI_SUCCESS) {
        printf("FAIL\n");
        exit(0);
      }   
    }   
  }   

  /* quit MPI */
  MPI_Finalize( );
  return 0;
}

两个程序的N值都相同,两个程序都没有从通信调用中返回错误。第二个程序应该至少快一点。但事实并非如此,它在大约34秒时慢得多 - 大约慢了12倍!

这个问题只能出现在一台机器上,而不是其他机器,即使它们运行相同的操作系统(Ubuntu)并且没有完全不同的硬件。另外,我在两者上都使用OpenMPI。

我真的把头发拉了出来,有没有人有想法?

感谢阅读!

1 个答案:

答案 0 :(得分:2)

一些观察结果。

MPI_Bcast正在将结果接收到“&amp; i”缓冲区中。 MPI_Recv将结果接收到“&amp; value”。有没有理由做出决定?

Send / Recv模型自然会同步。 MPI_Send调用是阻塞和序列化的。调用MPI_Send时,匹配的MPI_Recv应始终就绪。

一般而言,随着工作规模的扩大,集体倾向于拥有更大的优势。

我使用IBM Platform MPI编译并运行程序。我将N值降低了100倍至1000万,以加快测试速度。我更改了MPI_Bcast以在“&amp; value”缓冲区中接收结果,而不是在“&amp; i”缓冲区中。我对每个案例进行了三次处理,并将时间平均化。时间是“时间”返回的“真实”值(这是必要的,因为队列是从mpirun命令远程运行的)。

共享内存有4个等级,Send / Recv模型需要6.5秒,Bcast模型需要7.6秒。

有32个等级(8个/节点x 4个节点,FDR InfiniBand),发送/接收模型花了79秒,Bcast模型用了22秒。

拥有128个等级(16个/节点x 8个节点,FDR Infiniband),发送/接收模型需要134秒,Bcast模型需要44秒。

鉴于N值减少100倍至10000000之后的这些时间,我将建议“2.7秒”时间是无操作。仔细检查一些实际工作是否完成。