c - mpi程序出现不可预知的错误——主进程运行两次
问题描述
#include <stdio.h>
#include "mpi.h"
int main(int argc, char *argv[])
{
int rank, value, size,count;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
count=2*size-1;
while(count>0){
if (rank==0) {
// fprintf(stderr, "\nPlease give new value=");
printf("please input value= ");
scanf("%d",&value);
// fprintf(stderr, "%d read <-<- (%d)\n",rank,value);
printf("%d read <-<- (%d)\n",rank,value);
count-=1;
if (size>1) {
MPI_Send(&value, 1, MPI_INT, rank+1, 0, MPI_COMM_WORLD);
// fprintf(stderr, "%d send (%d)->-> %d\n", rank,value,rank+1);
printf("%d send (%d)->-> %d\n",rank,value,rank+1);
count-=1;
}
}
else {
MPI_Recv(&value, 1, MPI_INT, rank-1, 0, MPI_COMM_WORLD, &status);
// fprintf(stderr, "%d receive(%d)<-<- %d\n",rank, value, rank-1);
printf("%d receive(%d)<-<- %d\n",rank, value, rank-1);
count-=1;
if (rank<size-1) {
MPI_Send(&value, 1, MPI_INT, rank+1, 0, MPI_COMM_WORLD);
fprintf(stderr, "%d send (%d)->-> %d\n", rank, value, rank+1);
count-=1;
}
}
MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Finalize();
}
该程序的功能是在进程之间传递数字。现在我打开两个传递数字 4 的进程
但是 0 进程运行了两次,并没有达到预期的效果。
然后我用gdb调试
这一直困扰着我很长时间,我不太擅长从命令行看变量。请帮我。
解决方案
TL;DR:它运行两次,因为while
循环执行了两次。
但是 0 进程运行了两次,并没有达到预期的效果。
您的印象是进程0
运行了两次,因为count
在进入while
循环之前的变量的值是3
from count=2*size-1;
(size
是 2,因为您正在运行 2 个进程)。
在你的循环中:
while(count>0){
if (rank==0) {
...
count-=1;
if (size>1) {
...
count-=1;
}
}
else {
...
count-=1;
if (rank<size-1) {
...
count-=1;
}
}
MPI_Barrier(MPI_COMM_WORLD);
}
对于(进程0),该count
变量减少了两次,因此count
为1,并且由于while
循环条件是count>0
,它在退出之前再次执行。因此,进程0
“再次运行”。
该过程将变量0
递减两次,而该过程仅减少一次,因此很可能是一个错误。您可能会遇到进程阻塞等待从进程接收消息但进程已经在循环之外的情况。count
1
1
0
0
要测试进程中消息的发送和接收,请0
尝试以下操作:
int main(int argc, char *argv[])
{
int rank, value, size,count;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (rank==0)
{
printf("please input value= ");
scanf("%d",&value);
for(int i = 1; i < size; i++){
MPI_Send(&value, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
printf("%d send (%d)->-> %d\n",rank, value, i);
}
}
else
{
MPI_Recv(&value, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
printf("%d receive(%d)<-<- %d\n",rank, value, rank-1);
}
MPI_Finalize();
}
进程0
向所有剩余进程发送一个值:
for(int i = 1; i < size; i++){
MPI_Send(&value, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
printf("%d send (%d)->-> %d\n",rank, value, i);
}
并且所有剩余的进程都会收到来自进程的消息0
:
MPI_Recv(&value, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
推荐阅读
- reactjs - 在 SSR 上反应水合
- c++ - URLDownloadToFile 函数在 Windows XP 上返回 INET_E_DOWNLOAD_FAILURE
- javascript - 如何将javascript表格放入谷歌表格?
- c# - 24 位彩色 Ansi Win32 获取屏幕缓冲区位置的背景属性和字符
- deep-learning - 运行零镜头模型时错误说明缺少标记器
- c# - 如何将时间戳值参数从 C# 传递到 SQL
- regex - 查找超过四位数的词
- html - 无法从 mysql 检索数据到 django 中的 html 模板(PyCharm)
- javascript - 在反应挂钩中删除后数据未刷新
- javascript - React:PureComponent 和组件原型