Parallel processing MPI_Waitall()行为给定的MPI_请求数组可能具有异步发送/接收的未初始化插槽

Parallel processing MPI_Waitall()行为给定的MPI_请求数组可能具有异步发送/接收的未初始化插槽,parallel-processing,mpi,hpc,Parallel Processing,Mpi,Hpc,我遇到了一个场景,在这个场景中,我需要分配一个类型为MPI_Request的静态数组来跟踪异步发送和接收MPI操作。我总共有8个Isend和Irecv操作,其中4个是Isend,其余的是Irecv。但是,我并不是同时调用这8个函数。根据传入的数据,这些函数是成对调用的,这意味着我可以同时调用1个发送/接收或2个发送/接收或3个发送/接收或全部。事实上,他们将被称为成对的是肯定的,但有多少人将被称为是不确定的。下面是一个伪代码: MPI_Request reqs[8]; MPI_Status st

我遇到了一个场景,在这个场景中,我需要分配一个类型为MPI_Request的静态数组来跟踪异步发送和接收MPI操作。我总共有8个Isend和Irecv操作,其中4个是Isend,其余的是Irecv。但是,我并不是同时调用这8个函数。根据传入的数据,这些函数是成对调用的,这意味着我可以同时调用1个发送/接收或2个发送/接收或3个发送/接收或全部。事实上,他们将被称为成对的是肯定的,但有多少人将被称为是不确定的。下面是一个伪代码:

MPI_Request reqs[8];
MPI_Status stats[8];

if (Rank A exists){
    //The process have to send data to A and receive data from A
    MPI_Isend(A, ..., &reqs[0]);
    MPI_Irecv(A, ..., &reqs[1]);
}
if(Rank B exists){
    //The process have to send data to B and receive data from B
    MPI_Isend(B, ..., &reqs[2]);
    MPI_Irecv(B, ..., &reqs[3]);
}
if(Rank C exists){
    //The process have to send data to C and receive data from C
    MPI_Isend(C, ..., &reqs[4]);
    MPI_Irecv(C, ..., &reqs[5]);
}
if(Rank D exists){
    //The process have to send data to D and receive data from D
    MPI_Isend(D, ..., &reqs[6]);
    MPI_Irecv(D, ..., &reqs[7]);
}
//Wait for asynchronous operations to complete
MPI_Waitall(8, reqs, stats);
现在,我不确定程序的行为会是什么。总共有8个不同的异步发送和接收函数调用,每个调用的
MPI_reqs[8]
中的每个函数都有一个插槽,但并非所有函数都将始终使用。当其中一些插槽未被调用时,
MPI_reqs[8]
中的一些插槽将被取消初始化。但是,我需要
MPI_Waitall(8,需求,统计)
返回,无论
MPI_需求[8]
中的所有插槽是否初始化


有人能解释一下程序在这种特殊情况下的行为吗?

您可以使用
MPI\u REQUEST\u NULL
设置/初始化那些丢失的请求。也就是说,为什么不

int count = 0;
...
Isend(A, &reqs[count++]);
...
MPI_Waitall(count, reqs, stats);

当然,不初始化该值并将其提供给某个从中读取的函数不是一个好主意。

即使我使用了count,我怎么知道reqs数组应该有多少长度呢?您显然需要初始化
count=0
。执行所有isend/irecv后,
reqs
将初始化其第一个
count
请求。我知道这是伪代码,但请记住MPI语义是
MPI-ISend(…,&reqs[count++])
MPI-ISend(…,reqs+count++)
确保我了解count的工作原理。我将MPI_请求数组的长度定义为8,因为总共有8个不同的非块函数调用。然后我将数组初始化为all
MPI\u REQUEST\u NULL
。毕竟,我收到了一些我认为是死锁的东西,执行过程不会继续下去。我还尝试用blocking
MPI\u recv()
替换
MPI\u Irecv()
,在该场景中,MPI\u Waitall()抛出了一个错误。@nmd\u 07您必须问一个包含的后续问题来讨论死锁或错误问题。@nmd\u 07,关键是,尽管需要为所有8个
MPI\u请求
对象预先保留内存,
count
跟踪您在运行时实际使用的内存数量。例如,如果上面的
if
语句中只有一个计算结果为true,那么当您到达末尾和
MPI_Waitall(count,reqs,stats)时,post将以
&reqs[count++]
的方式递增导致等待
reqs
中的前两个请求对象(以及
stats
中的前两个状态对象正在更新)。