【发布时间】:2012-05-16 11:06:01
【问题描述】:
我是 MPI 的新手。我有 4 个进程:进程 1 到 3 填充一个向量并将其发送到进程 0,进程 0 将向量收集到一个非常长的向量中。我有可以工作的代码(太长无法发布),但是进程 0 的 recv 操作很笨拙而且很慢。
概括地说,代码执行以下操作:
MPI::Init();
int id = MPI::COMM_WORLD.Get_rank();
if(id>0) {
double* my_array = new double[n*m]; //n,m are int
Populate(my_array, id);
MPI::COMM_WORLD.Send(my_array,n*m,MPI::DOUBLE,0,50);
}
if(id==0) {
double* all_arrays = new double[3*n*m];
/* Slow Code Starts Here */
double startcomm = MPI::Wtime();
for (int i=1; i<=3; i++) {
MPI::COMM_WORLD.Recv(&all_arrays[(i-1)*m*n],n*m,MPI::DOUBLE,i,50);
}
double endcomm = MPI::Wtime();
//Process 0 has more operations...
}
MPI::Finalize();
事实证明,endcomm - startcomm 占总时间的 50%(0.7 秒,而程序完成需要 1.5 秒)。
有没有更好的方法来接收来自进程 1-3 的向量并将它们存储在进程 0 的 all_arrays 中?
我查看了 MPI::Comm::Gather,但我不确定如何使用它。特别是,它是否允许我指定进程 1 的数组是 all_arrays 中的第一个数组,进程 2 的数组是第二个,等等?谢谢。
编辑:我删除了“慢”循环,而是将以下内容放在“if”块之间:
MPI_Gather(my_array,n*m,MPI_DOUBLE,
&all_arrays[(id-1)*m*n],n*m,MPI_DOUBLE,0,MPI_COMM_WORLD);
导致同样的缓慢性能。这是否与根进程在尝试下一个接收之前“等待”每个接收完成的事实有关?或者这不是正确的思考方式?
【问题讨论】:
-
只是一个简短的评论 - C++ 绑定在当前 MPI 标准版本 2.2 中已弃用,并将在即将推出的 MPI 3.0 中完全删除。出于可移植性的原因,建议您学习和使用 C 接口。
-
你的程序中
n和m有多大,你的机器之间有什么样的连接? -
Hristo,谢谢——我将代码更改为 C 接口。
-
suszterpatt-- n=3500,m=7,所以 n*m=24,500。我不知道如何确定连接。如果有帮助,现在我正在我的笔记本电脑 Macbook Pro 2.2 GHz Core i7 上测试此代码,但很快会在 sun Grid Engine 集群上运行它。
-
@covstat 应该没有连接问题,因为您在共享内存上。你期待看到什么样的表现?无论您使用哪种 MPI 操作,这种数据收集总是比最近邻居之间的交换慢。我对 Mac 不熟悉,所以也可能是操作系统/编译器/MPI 构建问题,这超出了我的知识范围。