为什么通信成功的 MPI_Status 会报告“-1”为来源
Why would the MPI_Status of a successful communication would report "-1" as source
请查看以下 MWE,它显示了在我看来使用 MPI_Irecv
和 MPI_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”,但事实就是如此。您也可以将此视为麻烦的迹象。
请查看以下 MWE,它显示了在我看来使用 MPI_Irecv
和 MPI_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”,但事实就是如此。您也可以将此视为麻烦的迹象。