我有一个我希望并行化的串行C++程序。我知道MPI的基础知识,MPI_Send
,MPI_Recv
等。基本上,我有一个数据生成算法,运行速度比数据处理算法快得多。目前它们是串联运行的,但我认为在根进程中运行数据生成,在从进程上完成数据处理,并从根发送消息给包含待处理数据的从站。这样,每个从属进程处理一个数据集,然后等待下一个数据集。当没有更多的工作时,MPI从属进程挂起
问题是,一旦根进程完成生成数据,程序就会挂起,因为从服务器正在等待更多。
这是问题的一个例子:
#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相当陌生,所以对我很感兴趣。
感谢
你的斐波那契实现是O(2^n)。你应该优化你的顺序算法。 – mfontanini
我知道。这不是我正在解决的实际问题,这只是我能想到的最简单的例子,它模拟了问题。 –
也许我错过了一些东西,但是在每个过程结束时不会有一个简单的障碍来解决您的问题? – suszterpatt