过去两年我一直在互联网上学习C ++,最后我需要深入研究MPI。我一直在搜索stackoverflow和其他互联网(包括http://people.sc.fsu.edu/~jburkardt/cpp_src/mpi/mpi.html和https://computing.llnl.gov/tutorials/mpi/#LLNL)。我想我已经掌握了一些逻辑,但是我很难绕过以下内容:
#include (stuff)
using namespace std;
vector<double> function(vector<double> &foo, const vector<double> &bar, int dim, int rows);
int main(int argc, char** argv)
{
vector<double> result;//represents a regular 1D vector
int id_proc, tot_proc, root_proc = 0;
int dim;//set to number of "columns" in A and B below
int rows;//set to number of "rows" of A and B below
vector<double> A(dim*rows), B(dim*rows);//represent matrices as 1D vectors
MPI::Init(argc,argv);
id_proc = MPI::COMM_WORLD.Get_rank();
tot_proc = MPI::COMM_WORLD.Get_size();
/*
initialize A and B here on root_proc with RNG and Bcast to everyone else
*/
//allow all processors to call function() so they can each work on a portion of A
result = function(A,B,dim,rows);
//all processors do stuff with A
//root_proc does stuff with result (doesn't matter if other processors have updated result)
MPI::Finalize();
return 0;
}
vector<double> function(vector<double> &foo, const vector<double> &bar, int dim, int rows)
{
/*
purpose of function() is two-fold:
1. update foo because all processors need the updated "matrix"
2. get the average of the "rows" of foo and return that to main (only root processor needs this)
*/
vector<double> output(dim,0);
//add matrices the way I would normally do it in serial
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < dim; j++)
{
foo[i*dim + j] += bar[i*dim + j];//perform "matrix" addition (+= ON PURPOSE)
}
}
//obtain average of rows in foo in serial
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < dim; j++)
{
output[j] += foo[i*dim + j];//sum rows of A
}
}
for (int j = 0; j < dim; j++)
{
output[j] /= rows;//divide to obtain average
}
return output;
}
上面的代码仅用于说明概念。我主要担心的是并行添加矩阵,但令我难以理解的是:
1)如果每个处理器只在该循环的一部分上工作(当然我必须修改每个处理器的循环参数)我用什么命令将A的所有部分合并回一个更新的A,所有处理器在他们的记忆中。我的猜测是我必须做一些Alltoall,其中每个处理器将其A部分发送给所有其他处理器,但我如何保证(例如)处理器3处理的第3行覆盖其他处理器的第3行,而不是意外排第1行。
2)如果我使用Alltoall inside函数(),必须允许所有处理器进入function(),或者我可以使用...来隔离function()。
if (id_proc == root_proc)
{
result = function(A,B,dim,rows);
}
...然后在function()内部处理所有的并行化。听起来很傻,我试图在一个处理器(带广播)上做很多工作,并且只是将大量耗时的for循环并行化。只是试图保持代码在概念上简单,以便我可以得到我的结果并继续前进。
3)对于平均部分,我确定如果我想要并行化它,我可以使用reduce命令,对吗?
另外,作为旁白:有没有办法调用Bcast()使其阻塞?我想用它来同步我的所有处理器(升级库不是一个选项)。如果没有,那么我将选择Barrier()。感谢您对这个问题的回答,感谢stackoverflow社区,让我了解过去两年如何编程! :)
答案 0 :(得分:2)
1)您正在寻找的功能是MPI_Allgather。 MPI_Allgather将允许您从每个处理器发送一行并在所有处理器上接收结果。
2)是的,您可以使用功能中的某些处理器。由于MPI功能与通信器一起工作,因此您必须为此创建单独的通信器。我不知道这是如何在C ++绑定中实现的,但C绑定使用MPI_Comm_create函数。
3)是的,请参阅MPI_Allreduce。
除此之外:Bcast会阻止进程,直到分配给该进程的发送/接收操作完成为止。如果你想等待所有处理器完成他们的工作(我不知道你为什么要这样做),你应该使用Barrier()。
额外注意:我不建议使用C ++绑定,因为它们已被折旧,您将找不到有关如何使用它们的具体示例。如果您想要C ++绑定,则Boost MPI是要使用的库,但它不包含所有MPI功能。