【发布时间】:2020-09-27 00:42:31
【问题描述】:
一个与我的代码结构相同的小示例串行代码如下所示。
PROGRAM MAIN
IMPLICIT NONE
INTEGER :: i, j
DOUBLE PRECISION :: en,ei,es
DOUBLE PRECISION :: ki(1000,2000), et(200),kn(2000)
OPEN(UNIT=3, FILE='output.dat', STATUS='UNKNOWN')
DO i = 1, 1000, 1
DO j = 1, 2000, 1
ki(i,j) = DBLE(i) + DBLE(j)
END DO
END DO
DO i = 1, 200, 1
en = 2.0d0/DBLE(200)*(i-1)-1.0d0
et(i) = en
es = 0.0d0
DO j = 1, 1000, 1
kn=ki(j,:)
CALL CAL(en,kn,ei)
es = es + ei
END DO
WRITE (UNIT=3, FMT=*) et(i), es
END DO
CLOSE(UNIT=3)
STOP
END PROGRAM MAIN
SUBROUTINE CAL (en,kn,ei)
IMPLICIT NONE
INTEGER :: i
DOUBLE PRECISION :: en, ei, gf,p
DOUBLE PRECISION :: kn(2000)
p = 3.14d0
ei = 0.0d0
DO i = 1, 2000, 1
gf = 1.0d0 / (en - kn(i) * p)
ei = ei + gf
END DO
RETURN
END SUBROUTINE CAL
我在集群上运行我的代码,一个节点上有 32 个 CPU,一个节点上有 32 个 CPU 共享总共 250 GB 内存。我最多可以使用 32 个节点。
每完成一次内层循环,就会收集一个数据。完成所有外循环后,总共需要收集 200 条数据。如果只用一个 CPU 执行内层 Loop,则需要 3 天以上(72 小时以上)。
我想分别对内循环和外循环进行并行化?有人能建议如何并行化这段代码吗?
我可以分别对内循环和外循环使用 MPI 技术吗?如果是这样,如何区分执行不同循环(内循环和外循环)的不同CPU?
另一方面,我看到有人提到混合 MPI 和 OpenMP 方法的并行化。我可以对外部循环使用 MPI 技术,对内部循环使用 OpenMP 技术吗?如果是这样,如何在每次内循环完成后收集一个数据到CPU,在所有外循环完成后总共收集200个数据到CPU。如何区分分别执行inner Loop和outer Loop的不同CPU?
或者,有人会提供任何其他关于并行化代码和提高效率的建议吗?非常感谢您。
【问题讨论】:
-
恐怕要很好地回答这个问题确实需要更多细节。混合 MPI+OpenMP 可能是实现此目的的好方法,但可以肯定地说,您需要提供更多详细信息,尤其是关于内存使用和数据依赖关系的信息,以及说明您正在尝试实现的目标的最小示例将非常有帮助。
-
请注意,MPI 将要求您重写整个循环,甚至可能重写整个代码,因为它需要在每个处理器上使用不同的
j开始和结束值。您是否尝试过任何编译器开关? -
@Ian Bush,高性能标记和wander95 非常感谢您的回复。如果我正在运行我的代码,我已经用一个小的示例序列代码和集群信息修改了我的帖子。如果您能为并行化提供任何解决方案,我将不胜感激。还是请您使用混合 MPI 和 OpenMP 方法修改这个小型串行示例代码?再次感谢您。
-
感谢您的示例。如果它被重新打开,我会试着找时间来回答。但是在您考虑并行性之前,我应该指出的一件事是,由于您以错误的顺序访问 ki 的元素,串行性能会很差 - 您应该真正尝试编写代码,以便您在第一时间移动最快的索引一个,不是最后一个。因此,在并行性之前,我建议您重写代码以处理 ki 转置,而不是像上面写的那样。
-
我不会通过电子邮件进行 - 我会尽力提供帮助,但我不是代码编写服务。我现在正在准备一些教学,如果我完成后有时间我会看看。但是这个想法是在你上面写的小代码上使用 MPI 作为外部循环,使用 OpenMP 作为内部循环。应该很容易,你为什么不试一试呢?
标签: fortran mpi openmp openmpi