MPI程序故障排查:Bcast同步异常与Sendrecv传输失效
MPI管道式数据传递程序问题排查与代码迭代
任务描述
编写一个MPI程序,实现0号进程的数据通过管道传递给所有其他进程,具体要求如下:
- 进程i必须从i-1进程接收数据,再将其发送给i+1进程,直至最后一个进程
- 0号进程从用户处读取整数,直到输入负数为止
- 必须使用
MPI_Sendrecv完成数据交互
问题与代码迭代
编写程序后遇到以下问题:
- 初始版本中调用
MPI_Bcast时,其他进程未等待0号进程生成数据就继续执行,导致逻辑错误 - 调整
MPI_Bcast执行顺序后,MPI_Sendrecv仍然无法正常工作,程序出现冻结
初始代码
最初使用list存储数据,错误地在0号进程输入数据前就执行了MPI_Bcast,且直接传递list对象给MPI函数(MPI无法直接处理C++容器),导致广播无效。
#include <stdio.h> #include <mpi.h> #include <iostream> #include <list> using namespace std; int proc_count, proc_this; int input; list <int> buf; list <int> nlist = {}; int siz = 0; int main(int argc, char** argv) { int tag = 1; MPI_Status Stat; MPI_Request request; int prev, next; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &proc_count); MPI_Comm_rank(MPI_COMM_WORLD, &proc_this); prev = proc_this - 1; next = proc_this + 1; cout << "size before = " << siz << endl; MPI_Bcast(&siz, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&nlist, siz, MPI_INT, 0, MPI_COMM_WORLD); cout << "size = " << siz << endl; if (proc_this == 0) { cout << "Enter an integer and a non-negative number "; cin >> input; while (input >= 0) { nlist.push_back(input); cout << "Enter an integer and a non-negative number "; cin >> input; } cout << "Was entered negative value \n"; siz = nlist.size(); } else if (proc_this != 0 and proc_this != proc_count - 1) { MPI_Sendrecv(&nlist, siz, MPI_INT, next, tag, &buf, siz, MPI_INT, prev, tag, MPI_COMM_WORLD, &Stat); printf("Proc No-%d send data to proc No-%d\n", prev, next); cout << "size siz= " << siz << endl; for (auto it = nlist.begin(); it != nlist.end(); it++) printf("Proc No-%d my data %d\n", proc_this, *it); } else printf("Last proc was reached!"); MPI_Finalize(); return 0; }
更新1
将list替换为vector,但仍在0号进程输入数据前执行MPI_Bcast,广播顺序错误,且尝试广播vector对象本身而非底层数据指针。
#include <stdio.h> #include <mpi.h> #include <iostream> #include <vector> using namespace std; int proc_count, proc_this; int input; vector <int> buf; vector <int> nlist = {}; int siz; int main(int argc, char** argv) { int tag = 1; MPI_Status Stat; MPI_Request request; int prev, next; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &proc_count); MPI_Comm_rank(MPI_COMM_WORLD, &proc_this); prev = proc_this - 1; next = proc_this + 1; cout << "size before = " << siz << endl; MPI_Bcast(&siz, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&nlist, siz, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&buf, siz, MPI_INT, 0, MPI_COMM_WORLD); if (proc_this == 0) { cout << "Enter an integer and a non-negative number "; cin >> input; while (input >= 0) { nlist.push_back(input); cout << "Enter an integer and a non-negative number "; cin >> input; } cout << "Was entered negative value \n"; siz = nlist.size(); buf.resize(siz); } else if (proc_this != 0 and proc_this != proc_count - 1) { cout << "buf size = " << buf.size() << endl; cout << "size = " << siz << endl; MPI_Sendrecv(nlist.data(), siz, MPI_INT, next, tag, buf.data(), siz, MPI_INT, prev, tag, MPI_COMM_WORLD, &Stat); printf("Proc No-%d send data to proc No-%d\n", proc_this, next); cout << "size siz= " << siz << endl; for (auto it = nlist.begin(); it != nlist.end(); it++) printf("Proc No-%d my data %d\n", proc_this, *it); } else printf("Last proc was reached!"); MPI_Finalize(); return 0; }
更新2
修复了MPI_Bcast的顺序(先让0号进程输入数据,再广播数据大小和内容),但MPI_Sendrecv的逻辑仍有问题,程序冻结。
#include <stdio.h> #include <mpi.h> #include <iostream> #include <vector> using namespace std; int proc_count, proc_this; int input; vector <int> buf = {}; vector <int> nlist = {}; int siz; int main(int argc, char** argv) { int tag = 1; MPI_Status Stat; MPI_Request request; int prev, next; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &proc_count); MPI_Comm_rank(MPI_COMM_WORLD, &proc_this); prev = proc_this - 1; next = proc_this + 1; cout << "size before = " << siz << endl; if (proc_this == 0) { cout << "Enter an integer and a non-negative number "; cin >> input; while (input >= 0) { nlist.push_back(input); cout << "Enter an integer and a non-negative number "; cin >> input; } cout << "Was entered negative value \n"; siz = nlist.size(); } MPI_Bcast(&siz, 1, MPI_INT, 0, MPI_COMM_WORLD); nlist.resize(siz); MPI_Bcast(nlist.data(), siz, MPI_INT, 0, MPI_COMM_WORLD); buf.resize(siz); if (proc_this != 0 and proc_this != proc_count - 1) { cout << "buf size = " << buf.size() << endl; cout << "size nlist = " << nlist.size() << endl; MPI_Sendrecv(nlist.data(), siz, MPI_INT, next, tag, buf.data(), siz, MPI_INT, prev, tag, MPI_COMM_WORLD, &Stat); printf("Proc No-%d send data to proc No-%d\n", proc_this, next); cout << "size siz= " << siz << endl; for (int it: nlist) cout << "Proc No- " << proc_this << " my data " << it << endl; } if (proc_this == proc_count - 1) printf("Last proc was reached!"); MPI_Finalize(); return 0; }
内容的提问来源于stack exchange,提问作者Kate
相关产品推荐
相关产品推荐

