异常MPI行为

异常MPI行为,mpi,Mpi,我想知道是否有人能解释一下 我将从代码开始: /* 使用锦标赛风格编码实现的屏障 */ //约束条件:进程数必须是2的幂,例如。 //2、4、8、16、32、64128等。 #包括 #包括 #包括 无效mybarrier(MPI_通信); //全局调试布尔 int verbose=1; int main(int argc,char*argv[]){ 整数秩; 整数大小; int i; 整数和=0; MPI_Init(&argc,&argv); MPI通信等级(MPI通信世界和等级); MPI_通

我想知道是否有人能解释一下

我将从代码开始:

/*
使用锦标赛风格编码实现的屏障
*/
//约束条件:进程数必须是2的幂,例如。
//2、4、8、16、32、64128等。
#包括
#包括
#包括
无效mybarrier(MPI_通信);
//全局调试布尔
int verbose=1;
int main(int argc,char*argv[]){
整数秩;
整数大小;
int i;
整数和=0;
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI_通信大小(MPI_通信世界和大小);
整数检查=大小;
//检查以确保进程数为2的幂
如果(秩==0){
while(选中>1){
如果(检查%2==0){
检查/=2;
}否则{
printf(“错误:进程数必须是2的幂!\n”);
MPI_中止(MPI_通信世界,1);
返回1;
}
}
}
/简单的任务,中间有障碍
对于(i=0;i<500;i++){
sum++;
}
mybarrier(MPI_COMM_WORLD);
对于(i=0;i<500;i++){
sum++;
}
如果(详细){
printf(“进程%d到达最终确定\n”,排名);
}
MPI_Finalize();
返回0;
}
无效mybarrier(MPI_通信){
//MPI变量
整数秩;
整数大小;
int*数据;
MPI_状态*状态;
//循环变量
int i;
INTA;
整数跳跃;
int complete=0;
int currentCycle=1;
//初始化MPI变量
MPI_通信等级(通信和等级);
MPI_通信大小(通信和大小);
//第1步,收集
而(!完成){
跳过=当前周期*2;
//如果currentCycle平均划分秩,则它是一个目标
如果((秩%currentCycle)==0){
//如果skip平均分配排名,则需要接收
如果((排名百分比跳过)=0){
MPI_Recv(数据,0,MPI_INT,秩+当前周期,99,通信,状态);
如果(详细){
printf(“1:%d自%d\n”,秩,秩+当前周期);
}
//否则,它需要发送。一旦发送,流程就完成了
}否则{
如果(详细){
printf(“1:%d到%d\n”,秩,秩-currentCycle);
}
MPI_发送(数据,0,MPI_INT,秩-当前周期,99,通信);
完整=1;
}
}
电流周期*=2;
//主进程将永远不会发送,因此此代码将允许它完成
如果(当前周期>=大小){
完整=1;
}
}
完成=0;
currentCycle=大小/2;
//第二步,散射
而(!完成){
//如果currentCycle为1,则这是最后一个循环
如果(当前周期==1){
完整=1;
}
跳过=当前周期*2;
//如果currentCycle平均分配秩,则它是一个目标
如果((秩%currentCycle)==0){
//如果skip平均划分排名,则需要发送
如果((排名百分比跳过)=0){
如果(详细){
printf(“2:%d到%d\n”,秩,秩+当前周期);
}
MPI_发送(数据,0,MPI_INT,秩+当前周期,99,通信);
//否则,它需要接收
}否则{
如果(详细){
printf(“2:%d等待%d\n”,秩,秩-currentCycle);
}
MPI_Recv(数据,0,MPI_INT,秩-当前周期,99,通信,状态);
如果(详细){
printf(“2:%d自%d\n”,秩,秩-currentCycle);
}
}
}
电流周期/=2;
}
}
预期行为 代码是将总和增加到500,等待所有其他进程使用阻塞MPI_Send和MPI_Recv调用达到该点,然后将总和增加到1000

集群上的观测行为 集群的行为符合预期

在我的机器上观察到异常行为 main函数中的所有进程都报告为99,我专门将其链接到mybarrier的第二个while循环的标记

此外 我的第一个草稿是用for循环编写的,有了for循环,程序在集群上也会按预期执行,但在我的机器上,执行永远不会完成,即使所有进程都调用MPI_Finalize(但没有一个进程超越它)

MPI版本 我的机器正在运行OpenRTE 2.0.2 群集正在运行OpenRTE 1.6.3

问题 我观察到,我的机器似乎一直在意外运行,而集群却正常执行。我编写的其他MPI代码也是如此。1.6.3和2.0.2之间是否有我不知道的重大变化


无论如何,我很困惑,我想知道是否有人能解释一下为什么我的机器似乎不能正确运行MPI。我希望我已经提供了足够的详细信息,但如果没有,我将很乐意提供您需要的任何其他信息。

您的代码有问题,可能正是这个问题导致了您看到的奇怪行为

您正在向
MPI\u Recv
例程传递一个尚未分配的
状态
对象。事实上,该指针甚至没有初始化,因此如果它恰好不是
NULL
,则
MPI\u Recv
将在内存中的任何位置写入,从而导致未定义的行为。正确的格式如下所示:

MPI_Status status;
...
MPI_Recv(..., &status);
或者,如果要使用堆:

MPI_Status *status = malloc(sizeof(MPI_Status));
...
MPI_Recv(..., status);
...
free(status);
此外,由于您没有使用receive返回的值,因此应改为使用
MPI\u STATUS\u IGNORE

MPI_Recv(..., MPI_STATUS_IGNORE);

你的代码有问题,也许这就是你看到的奇怪行为的原因

您正在向
MPI\u Recv
例程传递一个尚未分配的
状态
对象。事实上,该指针甚至没有初始化,因此如果它恰好不是
NULL
,则
MPI\u Recv
将结束写入