为什么通信成功的 MPI_Status 会报告“-1”为来源

Why would the MPI_Status of a successful communication would report "-1" as source

请查看以下 MWE,它显示了在我看来使用 MPI_IrecvMPI_ANY_SOURCE 完成的成功通信如何报告其源为整数值“-1”。

示例包含命令行输出,如下所示。在这行之后,它 SigFaults 作为“-1”索引稍后用作发送源。

Hi! (fun2) Hi! (fun1) Hi! (fun1) Hi! (fun2) Sent! 0 Flag was 1, source was -1, the error was 0, and statusflag was 0

Sent! 0 Flag was 1, source was -1, the error was 0, and statusflag was 0

#include <iostream>
#include "mpi.h"
#include <omp.h>
#include <list>
#include <set>
#include <vector>
#include <queue>

#include <stdio.h>



const int L = 10;


void fun2(int &ready){
    int world_size;
    int world_rank;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
    printf("Hi! (fun2)\n");
    // Build
    std::queue<int> Q;
    MPI_Request R[L];
    int buffer[L];
    int response[L];
    for (int i=0; i<L; ++i){
        Q.push(i);
    }
    int i=0;
    while (!Q.empty()){ 
        i = Q.front();
        buffer[i] = i;
        Q.pop();
        MPI_Ssend(&buffer[i], 1, MPI_INT,(int) ( (world_rank + 1) % world_size), 2501, MPI_COMM_WORLD);
        printf("Sent! %d\n", buffer[i]);
        MPI_Recv(&response[i], 1, MPI_INT, (int) ( (world_rank + 1) % world_size), i, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        printf("Recieved! %d\n", response[i]);
    }

    return;
}


void fun1(int &ready){
    int world_size;
    int world_rank;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
    printf("Hi! (fun1)\n");
    // Build
    int V[world_size];
    int bigger_V[L];
    const int BATCH = 4;
    MPI_Request R[BATCH];
    MPI_Request R2[L];
    int buffer[L];
    int answers[L];
    int j = 0;
    int atomic_int;
    int statusflag = 0;
    bool first = true;

    int b=0;
    for (int i=0; i<L; ++i) {

        // MPI_ANY_SOURCE is used here!
        statusflag = MPI_Irecv(&buffer[i], 1, MPI_INT, MPI_ANY_SOURCE, 2501, MPI_COMM_WORLD, &R2[i]);
        MPI_Status status; 
        int flag;
        MPI_Wait(&R2[i], &status);
        MPI_Request_get_status(R2[i], &flag, &status); // This status has MPI_SOURCE = -1 !!!
        int q = status.MPI_SOURCE;
        printf("Flag was %d, source was %d, the error was %d, and statusflag was %d\n\n\n",
               flag, q, status.MPI_ERROR, statusflag);std::cout<<std::flush;

        answers[i] = i*5;
        MPI_Ssend(&answers[i], 1, MPI_INT, status.MPI_SOURCE, i, MPI_COMM_WORLD);

    }
    

    return;
}




int main(int argc, char** argv){
    int ready = 0;
    int provided;
    MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);

#pragma omp parallel num_threads(2)
{
long MYNUM = omp_get_thread_num();  

    if (MYNUM == 0){
        fun1(ready);
    }
    else {
        fun2(ready);
    }

}
MPI_Finalize();
}

为了编译,特提供如下一行:

mpic++ -fopenmp mwe.cpp ; mpirun -n 2 ./a.out

你的问题是你使用了MPI_Request_get_status:

MPI_Wait(&R2[i], &status);
MPI_Request_get_status(R2[i], &flag, &status);

您是否看到有两个调用都将 status 作为输出?很可疑。

您的 MPI_Wait 已经清除了请求对象(这就是它通过引用传递的原因),因此 MPI_Request_get_status 给出了垃圾输出。此调用适用于您希望在不执行等待调用的情况下检查状态的情况。您应该在等待呼叫后完成 status.MPI_SOURCE

顺便说一下,值“-1”是 MPI_PROC_NULL。我真的希望他们能做出那个“-2”,但事实就是如此。您也可以将此视为麻烦的迹象。