我有一个希望并行化的串行 C++ 程序。我知道 MPI、 、 等的基础知识MPI_Send
。MPI_Recv
基本上,我有一个数据生成算法,其运行速度明显快于数据处理算法。目前它们串联运行,但我想在根进程中运行数据生成,在从属进程上完成数据处理,然后从根向包含要处理的数据的从属发送消息。这样,每个从站处理一个数据集,然后等待下一个数据集。
问题是,一旦根进程完成生成数据,程序就会挂起,因为从属进程正在等待更多。
这是问题的一个例子:
#include "mpi.h"
#include <cassert>
#include <cstdio>
class Generator {
public:
Generator(int min, int max) : value(min - 1), max(max) {}
bool NextValue() {
++value;
return value < max;
}
int Value() { return value; }
private:
int value, max;
Generator() {}
Generator(const Generator &other) {}
Generator &operator=(const Generator &other) { return *this; }
};
long fibonnaci(int n) {
assert(n > 0);
if (n == 1 || n == 2) return 1;
return fibonnaci(n-1) + fibonnaci(n-2);
}
int main(int argc, char **argv) {
MPI_Init(&argc, &argv);
int rank, num_procs;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
if (rank == 0) {
Generator generator(1, 2 * num_procs);
int proc = 1;
while (generator.NextValue()) {
int value = generator.Value();
MPI_Send(&value, 1, MPI_INT, proc, 73, MPI_COMM_WORLD);
printf("** Sent %d to process %d.\n", value, proc);
proc = proc % (num_procs - 1) + 1;
}
} else {
while (true) {
int value;
MPI_Status status;
MPI_Recv(&value, 1, MPI_INT, 0, 73, MPI_COMM_WORLD, &status);
printf("** Received %d from process %d.\n", value, status.MPI_SOURCE);
printf("Process %d computed %d.\n", rank, fibonnaci(2 * (value + 10)));
}
}
MPI_Finalize();
return 0;
}
显然,并非以上所有内容都是“良好做法”,但足以说明问题。
如果我while(true)
从从属进程中删除 ,则程序会在每个从属进程退出时退出。我希望程序仅在根进程完成其工作并且所有从属进程都处理了已发送的所有内容后退出。
如果我知道将生成多少数据集,我可以运行那么多进程并且一切都会很好地退出,但这里不是这样。
有什么建议么?API中有什么可以做到这一点吗?可以通过更好的拓扑更好地解决这个问题吗?会MPI_Isend
或MPI_IRecv
做得更好吗?我对 MPI 还很陌生,所以请耐心等待。
谢谢