【发布时间】:2015-04-01 19:17:43
【问题描述】:
我遇到了一个问题,因为我正在用 C 语言编写一个并行分子动力学算法,其中所有核心计算最小的碰撞时间,然后通过 MPI_Allgather 将碰撞伙伴传送给所有其他核心,以查看哪个碰撞是最早的。 我已经内置了一个时间测量函数来查看我的程序的不同部分是如何缩放的。这表明,对于 8 个节点(192 个核心),Allgather 需要 2000 秒来处理 100k 时间步长,而对于 20 个节点(480 个)需要 5000 秒。
我在具有以下标志的 Cray 系统上使用 Cray 编译器:
add_definitions(-DNDEBUG)
set(CMAKE_C_FLAGS "-O3 -h c99,pl=./compiler_information,wp")
set(CMAKE_EXE_LINKER_FLAGS "-h pl=./compiler_information,wp")
部分代码如下所示:
MPI_Barrier(cartcomm);
START(scmcdm_Allgather); // time measure
MPI_Allgather(v_min_cpartner, 1, mpi_vector5, min_cpartners, 1, mpi_vector5, cartcomm);
STOP(scmcdm_Allgather); // time measure
其中 mpi_vector5 是包含 5 个双精度数的连续数据类型:
MPI_Type_contiguous(5, MPI_DOUBLE, &mpi_vector5);
这是正常行为吗?我该如何优化?
更新: 感谢您的 cmets,我实施了其他 2 种解决问题的方法:
- 如果所有核心在给定时间步内确实发生了冲突,则首先发送一个整数值(只有少数会发生冲突),然后只有发生冲突的核心将其传达给核心 0,然后再广播最小值。
这里第一步很慢,所有内核都与内核 0 通信。MPI 中是否有可能跳过这一步并有一个只有部分内核参与的集体通信例程? (即有最小值的那些)
- 我没有与vector5 通信,而是使用了一个带有碰撞时间和秩的double_int 对来使用minloc 函数。具有最短冲突时间的核心然后广播向量5。
这个解决方案是迄今为止最快的,但它的扩展性仍然是负的(8 个节点上 1600 秒,20 节点上 3000 秒)。
还有什么想法吗?
【问题讨论】:
-
如果你只对最早的事件感兴趣,你可以合并
MPI_Allgather()和循环搜索最早的事件:aMPI_Allreduce()using a customized operation (finding early) 可以做到诡计。见example。 -
@francis 有一个很好的观点——这里的一个问题是,在这种情况下,数据量必然会随着 MPI 任务的数量线性增加。至少有一个answer here关于自定义操作和查找最小值的位置,可能还有其他的。