简体   繁体   English

OpenMPI v / s Mvapich2:没有MPI_Recv的MPI_Send

[英]OpenMPI v/s Mvapich2: MPI_Send without MPI_Recv

I am trying to test the effects of MPI_Send without MPI_Recv . 我正在尝试在没有MPI_RecvMPI_Send下测试MPI_Send的效果。 I have the following program which I compile and run using openmpi-1.4.5 and mvapich2-1.9. 我有以下程序,我使用openmpi-1.4.5和mvapich2-1.9进行编译和运行。 I am aware that these implementations are for 2 different versions of the MPI standard, but I think MPI_Send and MPI_Recv are same across these standards: 我知道这些实现是针对MPI标准的2个不同版本的,但是我认为MPI_SendMPI_Recv在这些标准中是相同的:

#include <mpi.h>
#include <iostream>
#include <assert.h>

using namespace std;

MPI_Comm ping_world;
int mpi_size, mpi_rank;

void* ping(void* args)
{
    int ctr = 0;
    while(1)
    {
            char buff[6] = "PING";
            ++ctr;
            for(int i=0; i<mpi_size; ++i)
            {
                    cout << "[" << ctr << "] Rank " << mpi_rank << " sending " << buff << " to rank " << i << endl;
                    MPI_Send(buff, 6, MPI_CHAR, i, 0, ping_world);
            }
    }
}

int main(int argc, char *argv[])
{
int provided;
MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
assert(provided == MPI_THREAD_MULTIPLE);

MPI_Comm_rank (MPI_COMM_WORLD, &mpi_rank);
MPI_Comm_size (MPI_COMM_WORLD, &mpi_size);

    {
            MPI_Group orig_group;
            MPI_Comm_group(MPI_COMM_WORLD, &orig_group);
            int ranks[mpi_size];
            for(int i=0; i<mpi_size; ++i)
                    ranks[i] = i;

            MPI_Group new_group;
            MPI_Group_incl(orig_group, mpi_size, ranks, &new_group);
            MPI_Comm_create(MPI_COMM_WORLD, new_group, &ping_world);
    }

pthread_t th_ping;
pthread_create(&th_ping, NULL, ping, (void *) NULL);

pthread_join(th_ping, NULL);

return 0;
}

With mvapich2, I always get the following output (nothing more than this). 使用mvapich2,我总是得到以下输出(仅此而已)。 Basically, the program seems to have hanged after the 3 lines: 基本上,该程序似乎在3行之后挂起了:

[1] Rank 0 sending PING to rank 0
[1] Rank 1 sending PING to rank 0
[1] Rank 1 sending PING to rank 1

With openmpi, I get the following output (unending): 使用openmpi,我得到以下输出(无止境):

[1] Rank 1 sending PING to rank 0
[1] Rank 1 sending PING to rank 1
[1] Rank 0 sending PING to rank 0
[1] Rank 0 sending PING to rank 1
[2] Rank 0 sending PING to rank 0
[2] Rank 0 sending PING to rank 1
[3] Rank 0 sending PING to rank 0
[3] Rank 0 sending PING to rank 1
[4] Rank 0 sending PING to rank 0
[4] Rank 0 sending PING to rank 1
[5] Rank 0 sending PING to rank 0
[2] Rank 1 sending PING to rank 0
[2] Rank 1 sending PING to rank 1
[3] Rank 1 sending PING to rank 0
[3] Rank 1 sending PING to rank 1
[4] Rank 1 sending PING to rank 0
[4] Rank 1 sending PING to rank 1
[5] Rank 1 sending PING to rank 0
[5] Rank 1 sending PING to rank 1
[6] Rank 1 sending PING to rank 0

Questions: 问题:

  1. Why is there such a difference? 为什么会有这样的差异?
  2. How do I achieve the behavior similar to openmpi (unending) using mvapich2? 我如何使用mvapich2实现类似于openmpi(无止境)的行为?

MPI_Send can return when the buffer can be safely reused by the calling program. 当调用程序可以安全地重用缓冲区时,MPI_Send可以返回。 Nothing else is guaranteed, but there are many different implementation dependent behaviors. 没有其他保证,但是有许多不同的实现相关行为。 Different implementations can handle the buffering of messages differently. 不同的实现可以不同地处理消息的缓冲。 Eager protocols also allow for the transport of some short(er) messages to the receive rank without the need for a matching MPI_Recv to be posted. 急切的协议还允许将一些短消息传输到接收列,而无需发布匹配的MPI_Recv。

If you need MPI to enforce the message being received before the blocking send returns, look at MPI_Ssend. 如果在阻塞发送返回之前需要MPI来强制接收消息,请查看MPI_Ssend。

It's an incorrect MPI program to send data without receiving it. MPI程序发送数据而不接收它是不正确的。 The problem you're seeing is that your sends aren't matching any receives. 您看到的问题是您的发送与任何接收都不匹配。 Depending on the implementation, MPI_SEND might block until the message is actually received on the other end. 根据实现的不同, MPI_SEND可能会阻塞,直到在另一端实际收到该消息为止。 In fact, all implementations that I know of will do this for sufficiently large messages (though your message of 6 bytes probably isn't hitting that threshold anywhere). 实际上,我所知道的所有实现都将对足够大的消息执行此操作(尽管您的6字节消息可能未在任何地方达到该阈值)。

If you want to send messages without blocking, you need to use MPI_ISEND . 如果要发送消息而不阻塞,则需要使用MPI_ISEND However, even for this, you need to eventually call MPI_TEST or MPI_WAIT to be sure that the data was actually send, rather than just being buffered locally. 但是,即使如此,您最终还是需要调用MPI_TESTMPI_WAIT来确保数据是实际发送的,而不是仅在本地缓冲的。

I'm not sure about the specifics of why MVAPICH2 hangs while Open MPI doesn't, but in the end it doesn't really matter. 我不确定为什么MVAPICH2挂起而Open MPI不会挂起的具体细节,但最终这并不重要。 You need to modify your program or you're just testing cases that shouldn't really be used anyway. 您需要修改程序,或者只是测试不应该使用的用例。

In MVAPICH2(and MPICH) implementation, the self blocking send is blocked(not buffered) until corresponding MPI_Recv is found. 在MVAPICH2(和MPICH)实现中,自阻塞发送被阻塞(未缓冲),直到找到相应的MPI_Recv。 That is the reason it didn't hang at "Rank 1 sending PING to rank 0" It is just an implementation choice. 这就是它没有挂在“等级1发送PING到等级0”上的原因,这只是一种实现选择。

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

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