【问题标题】:MPI Send and receive questionsMPI 发送和接收问题
【发布时间】:2012-03-13 14:26:38
【问题描述】:

我对 MPI 发送和接收操作有疑问。

假设,我们有 2 个 MPI 线程尝试相互发送消息。以下是执行此操作的三个代码 sn-ps:

首先(阻止“发送”和“接收”):

...
int data = ...;
...
MPI_Send( &data, sizeof( int ), MPI_INT, 
        (my_id == 0)?1:0, 0, MPI_COMM_WORLD );

MPI_Status status; 
MPI_Recv( &data, sizeof( int ), MPI_INT,
        (my_id == 0)?1:0, 0, MPI_COMM_WORLD, &status );
...

第二个(非阻塞“发送”但阻塞“接收”):

...
int data = ...;
...
MPI_Request request;
MPI_Isend( &data, sizeof( int ), MPI_INT, 
        (my_id == 0)?1:0, 0, MPI_COMM_WORLD, &request);

MPI_Status status; 
MPI_Recv( &data, sizeof( int ), MPI_INT,
        (my_id == 0)?1:0, 0, MPI_COMM_WORLD, &status );
// Synchronize sender & receiver
MPI_Wait( &request, &status);
...

第三(非阻塞“接收”和阻塞“发送”):

...
int data = ...;
...
MPI_Request request;
MPI_Irecv( &data, sizeof( int ), MPI_INT,
        (my_id == 0)?1:0, 0, MPI_COMM_WORLD, &request );

MPI_Send( &data, sizeof( int ), MPI_INT, 
        (my_id == 0)?1:0, 0, MPI_COMM_WORLD);

MPI_Status status; 

// Synchronize sender & receiver
MPI_Wait( &request, &status);
...

我猜以上三个代码可能存在问题,但我想听听您的意见。所以,我有以下问题:

  1. 上面给出的 3 个代码有哪些(潜在)问题(如果有)?

  2. 考虑到 MPI 标准,以上三个代码中哪一个是有效/正确的,以便它可以与所有 MPI 实现一起使用?

  3. 最好的方法是什么(如果不是以上 3 种,请写出来)?

  4. 在第三个代码中,如果我们改变 MPI_Irecv 和 MPI_Send 调用的顺序呢?

PS:顺便说一句,我已经尝试使用 Scali MPI 执行它们并且它们都有效!

【问题讨论】:

    标签: c mpi


    【解决方案1】:

    您的第一个实现可能会导致死锁,尤其是在同步模式下完成通信时(可能它在您的测试中有效,因为通信被缓冲了;对于大数据而言,情况不太可能)。

    其他两个实现应该在没有死锁的情况下工作。我相信在发送之前启动接收操作被认为是更好的做法,所以我个人倾向于第三种实现。来自MPI standard, section 3.7

    给用户的建议

    [...]

    消息传递模型意味着通信由发送者发起。如果在发送方发起通信时已经发布了接收,则通信通常会具有较低的开销(数据可以直接移动到接收缓冲区,并且不需要排队等待发送请求)。但是,接收操作只有在匹配的发送发生后才能完成。使用非阻塞接收可以实现较低的通信开销,而不会在接收器等待发送时阻塞接收器。

    使用顺序为MPI_Send/MPI_Irecv 的第三个实现可能会在MPI_Send 调用中死锁,原因与第一个实现相同。

    【讨论】:

    • 我也对第二个实现持怀疑态度,因为我们有一个阻塞接收,它应该阻塞直到接收到数据。那么,这种情况下不需要 MPI_Wait() 吗?
    • @user600029 我认为在这种情况下不存在任何死锁风险,因为两个进程在阻塞接收之前已经启动了它们的发送操作。
    • @user600029 但是,我刚刚意识到,在您的所有实现中,您只分配了一个数据,其地址同时用于发送和接收操作。在第二个和第三个实现中,这种结果是不可预测的。如果您真的想在两个进程中交换 data 的值,则必须至少在其中一个中复制存储(但如果您坚持使用不能保证的异步通信方案,则很可能在两个中都复制)通讯订单)
    • @user600029 在示例 2 中,您仍应使用 MPI_Wait 来清理发送请求。或者您可以使用MPI_Request_free 而不是等待。但请记住,在发送完成之前写入发送缓冲区是不安全的 - 您可以使用 MPI_Wait 进行检查。
    猜你喜欢
    • 2018-08-30
    • 2018-04-25
    • 2013-04-15
    • 2018-03-12
    • 2013-12-20
    • 2016-06-15
    • 1970-01-01
    • 2011-07-04
    • 2016-10-03
    相关资源
    最近更新 更多