Error handling 在不同的通信器中接收到MPI消息-程序错误或MPI实施错误?
这是对的后续行动,其结论是程序错误,因此预期行为未定义 我在这里尝试创建的是一个简单的错误处理机制,为此,我将对空消息的Irecv请求用作“中止句柄”,将其附加到我的正常Error handling 在不同的通信器中接收到MPI消息-程序错误或MPI实施错误?,error-handling,mpi,intel-mpi,Error Handling,Mpi,Intel Mpi,这是对的后续行动,其结论是程序错误,因此预期行为未定义 我在这里尝试创建的是一个简单的错误处理机制,为此,我将对空消息的Irecv请求用作“中止句柄”,将其附加到我的正常MPI_Wait调用(并将其转换为MPI_WaitAny),为了允许我在进程0上发生错误时取消阻止进程1,并且它无法再到达应该发布匹配的MPI\u Recv的点 发生的情况是,由于内部消息缓冲,MPI\u Isend可能会立即成功,而另一个进程无法发布匹配的MPI\u Recv。所以再也没有办法取消了 我希望一旦所有进程调用MP
MPI_Wait
调用(并将其转换为MPI_WaitAny
),为了允许我在进程0上发生错误时取消阻止进程1,并且它无法再到达应该发布匹配的MPI\u Recv
的点
发生的情况是,由于内部消息缓冲,MPI\u Isend
可能会立即成功,而另一个进程无法发布匹配的MPI\u Recv
。所以再也没有办法取消了
我希望一旦所有进程调用MPI\u Comm\u free
,我就可以一劳永逸地忘记这个消息,但事实并非如此。相反,它被传送到以下通信器中的MPI\u Recv
因此,我的问题是:
MPI\u Isend
调用转换为MPI\u Issend
,程序将按预期工作-在这种情况下,我至少可以确保程序是正确的吗#包括“stdio.h”
#包括“unistd.h”
#包括“mpi.h”
#包括“time.h”
#包括“stdlib.h”
int main(int argc,char*argv[]){
int等级、大小;
MPI_组;
MPI_通信我的通信;
srand(时间(空));
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI_通信大小(MPI_通信世界和大小);
MPI通信集团(MPI通信世界和集团);
MPI通信创建(MPI通信世界、集团和我的通信);
如果(秩==0)printf(“已创建通讯器%d\n,我的通讯”);
如果(秩==1){
MPI_请求请求[2];
int msg=123,其中:;
MPI_Isend(&msg,1,MPI_INT,0,0,my_comm,&req[0]);
MPI_Irecv(NULL,0,MPI_INT,0,0,my_comm,&req[1]);
MPI_Waitany(2,请求和请求,MPI_状态忽略);
MPI\u屏障(我的通信);
if(which==0){
printf(“排名1:发送成功;取消中止句柄\n”);
MPI_取消(&req[1]);
MPI_等待(&req[1],MPI_状态_忽略);
}否则{
printf(“排名1:发送中止;取消发送请求\n”);
MPI_取消(&req[0]);
MPI_等待(&req[0],MPI_状态_忽略);
}
}否则{
MPI_请求请求;
int msg,r=rand()%2;
if(r){
printf(“等级0:接收消息\n”);
MPI_Recv(&msg,1,MPI_INT,1,0,my_comm,MPI_STATUS_IGNORE);
}否则{
printf(“秩0:发送中止消息\n”);
MPI_Isend(NULL、0、MPI_INT、1、0、my_comm和req);
}
MPI\u屏障(我的通信);
if(!r){
MPI_取消(&req);
MPI\u等待(&req,MPI\u状态\u忽略);
}
}
如果(秩==0)printf(“释放通讯器%d\n,我的通讯”);
MPI_通信免费(&my_通信);
睡眠(2);
MPI通信创建(MPI通信世界、集团和我的通信);
如果(秩==0)printf(“已创建通讯器%d\n,我的通讯”);
如果(秩==0){
MPI_请求请求;
MPI_状态;
int msg,取消;
MPI_Irecv(&msg,1,MPI_INT,1,0,my_comm,&req);
睡眠(1);
MPI_取消(&req);
MPI_等待(&req,&status);
MPI_测试已取消(&状态,&已取消);
如果(取消){
printf(“排名0:接收取消\n”);
}否则{
printf(“排名0:收到旧邮件!!!\n”);
}
}
如果(秩==0)printf(“释放通讯器%d\n,我的通讯”);
MPI_通信免费(&my_通信);
MPI_Finalize();
返回0;
}
产出:
created communicator -2080374784
rank 0: sending abort message
rank 1: send succeed; cancelling abort handle
freeing communicator -2080374784
created communicator -2080374784
rank 0: STRAY MESSAGE RECEIVED!!!
freeing communicator -2080374784
我尝试使用OpenMPI构建您的代码,但没有成功。mpicc抱怨
状态。已取消
error: ‘MPI_Status’ has no member named ‘cancelled’
我想这是英特尔mpi的一项功能。如果您切换为:
...
int flag;
MPI_Test_cancelled(&status, &flag);
if (flag) {
...
这将使用openmpi提供预期的输出(并减少代码的依赖性)。使用“英特尔mpi”时会出现这种情况吗
我们需要一位专家告诉我们什么是英特尔mpi中的状态。已取消,因为我对此一无所知
编辑:我测试了我的答案很多次,我发现输出是随机的,有时是正确的,有时不是。对不起。。。好像未设置处于状态的内容。部分答案可能在MPI\u Wait()
“仅当MPI例程的返回为MPI_ERR_IN_status时,才会设置状态返回的MPI_ERROR字段。该错误类仅由采用状态参数数组(MPI_Testall、MPI_Testsome、MPI_Waitall和MPI_Waitsome)的例程返回。”。在所有其他情况下,状态中MPI_错误字段的值保持不变。有关确切文本,请参阅MPI-1.1规范中的第3.2.5节。“如果MPI_Test_cancelled()使用MPI_错误,情况可能会变糟
所以这里有一个技巧:使用MPI_Waitall(1,&req,&status)
!最后输出是正确的 正如@kraffenetti在上述评论中提到的,这是一个错误的程序,因为发送的消息与接收的消息不匹配。即使消息被取消,它们仍然需要在远程端有一个匹配的接收,因为对于已发送的消息,取消可能不会成功,因为在完成取消之前已经发送了消息(这里就是这种情况)
这个问题在MPICH的票子上开始了一条线索,您可以在票子上找到更多细节。谢谢您的评论!我更新了