使用MPI_Barrier()后,MPI_Wtime()出现巨大差异
Huge difference in MPI_Wtime() after using MPI_Barrier()?
这是代码的一部分。
if(rank==0) {
temp=10000;
var=new char[temp] ;
MPI_Send(&temp,1,MPI_INT,1,tag,MPI_COMM_WORLD);
MPI_Send(var,temp,MPI_BYTE,1,tag,MPI_COMM_WORLD);
//MPI_Wait(&req[0],&sta[1]);
}
if(rank==1) {
MPI_Irecv(&temp,1,MPI_INT,0,tag,MPI_COMM_WORLD,&req[0]);
MPI_Wait(&req[0],&sta[0]);
var=new char[temp] ;
MPI_Irecv(var,temp,MPI_BYTE,0,tag,MPI_COMM_WORLD,&req[1]);
MPI_Wait(&req[0],&sta[0]);
}
//I am talking about this MPI_Barrier
MPI_Barrier(MPI_COMM_WORLD);
cout << MPI_Wtime()-t1 << endl ;
cout << "hello " << rank << " " << temp << endl ;
MPI_Finalize();
}
1.当使用MPI_Barrier时-正如预期的那样,所有过程花费的时间几乎相同,大约为0.02
2.当不使用MPI_Barrier()时-根进程(发送消息)等待一些额外的时间。并且CCD_ 1变化很大并且根处理所花费的时间大约为2秒。
如果我没有错的话,MPI_Barrier只用于将所有正在运行的进程置于同一级别。那么,为什么我使用MPI_Barrier()的时间不为2秒(所有进程中的最小值,例如root进程)呢。请解释一下?
感谢Wesley Bland注意到您在同一请求上等待了两次。以下是对实际发生的事情的解释。
MPI中的异步(非阻塞)操作称为进程。那就是实际转移发生的时候。在MPI库中,进程可以以许多不同的方式和在许多不同的点上进行。发布异步操作时,其进程可能会无限期推迟,甚至直到调用MPI_Wait
、MPI_Test
或某些会导致新消息被推送到发送/接收队列或从中拉出的调用。这就是为什么在非阻塞操作启动后尽快调用MPI_Wait
或MPI_Test
非常重要。
Open MPI支持后台进程线程,即使不满足上一段中的条件(例如,从未在请求句柄上调用MPI_Wait
或MPI_Test
),该线程也会小心地执行操作。在构建库时,必须显式启用此功能。默认情况下不会启用它,因为后台进程会增加操作的延迟。
在您的情况下,当您在接收器中第二次调用MPI_Wait
时,您正在等待错误的请求,因此第二次MPI_Irecv
操作的进程被推迟。消息大小超过40 KiB(10000乘以4字节+信封开销),高于Open MPI中的默认热切限制(32 KiB)。这样的消息是使用会合协议发送的,该协议要求发布和进行发送和接收操作。接收操作没有进展,因此秩0中的发送操作块,直到在某个时间点,秩1中的(MPI_Wtime -t1)
0调用的清理例程最终进行接收。
当您对MPI_Barrier
进行调用时,它会导致未完成接收的进行,其行为几乎就像对MPI_Wait
的隐式调用。这就是为什么发送秩0很快完成,并且两个进程都能及时继续。
注意,紧接着MPI_Wait
的MPI_Irecv
相当于简单地调用MPI_Recv
。后者不仅更简单,而且不太容易出现像你所做的那种简单的打字错误。
您正在两次等待同一请求以获得Irecv。第二个是一个需要所有时间的排名,由于它被跳过,排名0遥遥领先。
MPI_BARRIER可以实现为,如果进程进入算法,则某些进程可以先于其他进程离开算法。这可能就是这里发生的情况。
在我运行的测试中,我发现运行时几乎没有差异。主要的区别是,你似乎只运行了一次代码,而我在你的代码上循环了数千次,然后取了平均值。我的输出如下:
With the barrier
[0]: 1.65071e-05
[1]: 1.66872e-05
Without the barrier
[0]: 1.35653e-05
[1]: 1.30711e-05
所以我认为你看到的任何变化都是你的操作系统的结果,而不是你的程序。
此外,为什么要将MPI_Irecv与MPI_wait结合使用,而不仅仅是使用MPI_recv?
- 用MacOS Mojave编译C++:致命错误:mpi.h:没有这样的文件或目录
- 在linux上调试巨大的C++项目
- MPI突然停止了对多个核心的操作
- 设置 Visual Studio for MPI: 找不到标识符错误
- GCC 和 Clang 代码性能的巨大差异
- 使用 make 编译 MPI,几个命名空间错误,例如"错误:未知类型名称'使用'?
- 如何使用 MPI 的远程内存访问 (RMA) 功能并行化数据聚合?
- 重载 MPI 中的运算符 ()
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- MPI:检查是否有任何进程已终止
- 使用 pybind11 共享 MPI 通信器
- 使用 CMake,Microsoft MPI 和 Visual Studio 2017 找不到 mpi.h
- 在具有 MPI 的超立方体中广播
- 通过 mpi 发送 c++ 标准::矢量<bool>
- 使用 MPI 的 C++ 中的并行 for 循环
- 如何将 OpenMP 和 MPI 导入到大型 CLion CMake 项目中?
- 如何通过Boost.MPI发送2d Boost.MultiArray的子阵列?
- 将数字提高到一个巨大的指数
- 巨大的内存分配:堆栈与堆
- HDF5 构建了并行支持,但找不到特定于 mpi 的功能