MPI 在根進程上收集數組 (MPI gather array on root process)


問題描述

MPI 在根進程上收集數組 (MPI gather array on root process)

I'm new to MPI. I have 4 processes: processes 1 through 3 populate a vector and send it to process 0, and process 0 collects the vectors into one very long vector. I have code that works (too long to post), but process 0's recv operation is clumsy and very slow.

In abstract, the code does the following:

MPI::Init();
int id = MPI::COMM_WORLD.Get_rank();

if(id>0) {
    double* my_array = new double[n*m]; //n,m are int
    Populate(my_array, id);
    MPI::COMM_WORLD.Send(my_array,n*m,MPI::DOUBLE,0,50);
}

if(id==0) {
    double* all_arrays = new double[3*n*m];
    /* Slow Code Starts Here */
    double startcomm = MPI::Wtime();
    for (int i=1; i<=3; i++) {
    MPI::COMM_WORLD.Recv(&all_arrays[(i-1)*m*n],n*m,MPI::DOUBLE,i,50);
    }
    double endcomm = MPI::Wtime();
    //Process 0 has more operations...
}
MPI::Finalize();

It turns out that endcomm - startcomm accounts for 50% of the total time (0.7 seconds compared to 1.5 seconds for the program to complete).

Is there a better way to receive the vectors from processes 1-3 and store them in process 0's all_arrays?

I checked out MPI::Comm::Gather, but I'm not sure how to use it. In particular, will it allow me to specify that process 1's array is the first array in all_arrays, process 2's array the second, etc.? Thanks.

Edit: I removed the "slow" loop, and instead put the following between the "if" blocks:

MPI_Gather(my_array,n*m,MPI_DOUBLE,
    &all_arrays[(id-1)*m*n],n*m,MPI_DOUBLE,0,MPI_COMM_WORLD);

The same slow performance resulted. Does this have something to do with the fact that the root process "waits" for each individual receive to complete before attempting the next one? Or is that not the right way to think about it?


參考解法

方法 1:

Yes, MPI_Gather will do exactly that. From the anl page for MPI_Gather:

int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype, 
               void *recvbuf, int recvcnt, MPI_Datatype recvtype, 
               int root, MPI_Comm comm)

Here, sendbuf is your array on each process (my_array). recvbuf is the long array (all_arrays) on the receiving process into which short arrays are being gathered to. The short array on the receiving process is being copied into its contiguous position in the long array, so you don't need to worry about doing it yourself. The arrays from each process will be arranged contiguously in the long array.

EDIT:

In the case where the receiving process does not contribute sendbuf in the gathering, you may want to use MPI_Gatherv instead (Thanks to @HristoIliev for pointing this out).

(by covstatmilancurcic)

參考文件

  1. MPI gather array on root process (CC BY-SA 3.0/4.0)

#mpi #C






相關問題

MPI 在根進程上收集數組 (MPI gather array on root process)

如何為 xcode 安裝 Openmpi? (how to install Openmpi for xcode?)

在 ARM 上的 Linux 上運行 MPI (OpenMPI) 應用程序時出現問題 (Problems running MPI (OpenMPI) app on Linux on ARM)

在 C++ 和 MPI 中獨立並行寫入文件 (independent parallel writing into files in C++ and MPI)

傳輸一些數據後 MPI_Bcast 掛起 (MPI_Bcast hanging after some data transferred)

來自一個文件的多個 mpirun 與多個文件運行 (Multiple mpiruns from one file vs multiple file runs)

Isend/Irecv 不起作用,但 Send/Recv 可以 (Isend/Irecv doesn`t work but Send/Recv does)

MPI 要求在 localhost 上進行身份驗證 (MPI asks authentication on localhost)

MPI 生成和合併問題 (Issue with MPI spawn and merge)

mpiexec 拋出錯誤“mkstemp 失敗,沒有這樣的文件或目錄” (mpiexec throws error "mkstemp failed No such file or directory")

使用 MPI_Isend 時出現分段錯誤 (Segmentation Fault when using MPI_Isend)

MPI_Comm_split 不適用於 MPI_Bcast (MPI_Comm_split not working with MPI_Bcast)







留言討論