Я хочу использовать MPI_Iprobe, чтобы проверить, не отправлено ли сообщение с заданным тегом.Почему MPI_Iprobe возвращает false, когда сообщение определенно отправлено?
Однако поведение MPI_Iprobe не совсем так, как я ожидал. В приведенном ниже примере я отправляю сообщения из нескольких задач на одну задачу (ранг 0). Затем в ранге 0 я жду несколько секунд, чтобы дать много времени для завершения MPI_Isends. Затем, когда я запускаю MPI_Iprobe, он возвращается с флагом false. Если я повторяю после (блокирующего) MPI_Probe, он возвращает true.
#include "mpi.h"
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int rank;
int numprocs;
int tag;
int receive_tag;
int flag=0;
int number;
int recv_number=0;
MPI_Request request;
MPI_Status status;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
// rank 0 receives messages, all others send messages
if (rank > 0) {
number = rank;
tag = rank;
MPI_Isend(&number, 1, MPI_INT, 0, tag, MPI_COMM_WORLD,&request); // send to rank 0
printf("Sending tag : %d \n",tag);
}
else if (rank == 0) {
sleep(5); // [seconds] allow plenty of time for all sends from other tasks to complete
receive_tag = 3; // just try and receive a single message from task 1
MPI_Iprobe(MPI_ANY_SOURCE,receive_tag,MPI_COMM_WORLD,&flag,&status);
printf("After MPI_Iprobe, flag = %d \n",flag);
MPI_Probe(MPI_ANY_SOURCE,receive_tag,MPI_COMM_WORLD,&status);
printf("After MPI_Probe, found message with tag : %d \n",receive_tag);
MPI_Iprobe(MPI_ANY_SOURCE,receive_tag,MPI_COMM_WORLD,&flag,&status);
printf("After second MPI_Iprobe, flag = %d \n",flag);
// receive all the messages
for (int i=1;i<numprocs;i++){
MPI_Recv(&recv_number, 1, MPI_INT, MPI_ANY_SOURCE, i, MPI_COMM_WORLD,&status);
printf("Received : %d \n",recv_number);
}
}
MPI_Finalize();
}
дает этот вывод:
Sending tag : 4
Sending tag : 3
Sending tag : 2
Sending tag : 5
Sending tag : 1
After MPI_Iprobe, flag = 0
After MPI_Probe, found message with tag : 3
After second MPI_Iprobe, flag = 1
Received : 1
Received : 2
Received : 3
Received : 4
Received : 5
Почему обратный mpi_iprobe 'ложный' в первый раз?
Любая помощь была бы высоко оценена!
EDIT: после ответа Христо Илиев теперь у меня есть следующий код:
#include "mpi.h"
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int rank;
int numprocs;
int tag;
int receive_tag;
int flag=0;
int number;
int recv_number=0;
MPI_Request request;
MPI_Status status;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
// rank 0 receives messages, all others send messages
if (rank > 0) {
number = rank;
tag = rank;
MPI_Isend(&number, 1, MPI_INT, 0, tag, MPI_COMM_WORLD,&request); // send to rank 0
printf("Sending tag : %d \n",tag);
// do stuff
MPI_Wait(&request,&status);
printf("Sent tag : %d \n",tag);
}
else if (rank == 0) {
sleep(5); // [seconds] allow plenty of time for all sends from other tasks to complete
receive_tag = 3; // just try and receive a single message from task 1
MPI_Iprobe(MPI_ANY_SOURCE,receive_tag,MPI_COMM_WORLD,&flag,&status);
printf("After MPI_Iprobe, flag = %d \n",flag);
MPI_Probe(MPI_ANY_SOURCE,receive_tag,MPI_COMM_WORLD,&status);
printf("After MPI_Probe, found message with tag : %d \n",receive_tag);
MPI_Iprobe(MPI_ANY_SOURCE,receive_tag,MPI_COMM_WORLD,&flag,&status);
printf("After second MPI_Iprobe, flag = %d \n",flag);
// receive all the other messages
for (int i=1;i<numprocs;i++){
MPI_Recv(&recv_number, 1, MPI_INT, MPI_ANY_SOURCE, i, MPI_COMM_WORLD,&status);
}
}
MPI_Finalize();
}
который дает следующий результат:
Sending tag : 5
Sending tag : 2
Sending tag : 1
Sending tag : 4
Sending tag : 3
Sent tag : 2
Sent tag : 1
Sent tag : 5
Sent tag : 4
Sent tag : 3
After MPI_Iprobe, flag = 0
After MPI_Probe, found message with tag : 3
After second MPI_Iprobe, flag = 1
Спасибо, я только что попробовал заменить MPI_Isend на MPI_Send, как вы сказали, но по какой-то причине первый MPI_Iprobe все еще возвращает false. (То же самое происходит, если я использую MPI_Isend с MPI_Wait) ... –
Для информации, я добавил свой новый код и вывод в приведенном выше редактировании (в вопросе). –
'MPI_Iprobe' предназначен для использования в циклах с ожиданным циклом ожидания. Может потребоваться несколько вызовов 'MPI_Iprobe' до того, как операция будет выполнена правильно. «MPI_Probe» блокируется, и поэтому он не возвращается до того, как операция была выполнена до того момента, когда конверт сообщения был получен и согласован. –