【发布时间】:2011-11-13 14:58:43
【问题描述】:
有一个 mpi 版本的程序,它使用 COMMON 块来存储在代码中随处使用的数组。不幸的是,没有办法以 COMMON 块大小声明数组,只有运行时才知道该数组的大小。因此,作为一种解决方法,我决定将这些数组移到接受 ALLOCATABLE 数组的模块中。也就是说,COMMON 块中的所有数组都消失了,而是使用了 ALLOCATE。所以,这是我在程序中唯一改变的地方。不幸的是,该程序的性能很糟糕(与 COMMON 块的实现相比)。对于 mpi-settings,每个计算节点上都有一个 mpi-process,每个 mpi-process 都有一个线程。 我在这里找到了similar 的问题,但不认为(不明白:))它如何应用于我的案例(每个进程都有一个线程)。感谢您的帮助。
这是一个简单的例子,说明了我在说什么(下面是一个伪代码):
“源文件”:
SUBROUTINE ZEROSET()
INCLUDE 'FILE_1.INC'
INCLUDE 'FILE_2.INC'
INCLUDE 'FILE_3.INC'
....
INCLUDE 'FILE_N.INC'
ARRAY_1 = 0.0
ARRAY_2 = 0.0
ARRAY_3 = 0.0
ARRAY_4 = 0.0
...
ARRAY_N = 0.0
END SUBROUTINE
如您所见,ZEROSET() 没有并行或 MPI 的东西。 FILE_1.INC, FILE_2, ... , FILE_N.INC 是在 COMMON 块中定义 ARRAY_1, ARRAY_2 ... ARRAY_N 的文件。类似的东西
REAL ARRAY_1
COMMON /ARRAY_1/ ARRAY_1(NX, NY, NZ)
NX、NY、NZ 是在 PARAMETER 指令的帮助下定义明确的参数。 当我使用模块时,我只是销毁了所有 COMMON 块,所以 FILE_I.INC 看起来像
REAL, ALLOCATABLE:: ARRAY_I(:,:,:)
然后将上面的“INCLUDE 'FILE_I.INC'”语句更改为“USE FILE_I”。实际上,当并行程序执行时,一个特定的进程不需要整个(NX,NY,NZ)域,所以我计算参数然后分配ARRAY_I(仅ONCE!)。
子程序 ZEROSET() 使用 COMMON 块执行 0.18 秒,使用模块执行 0.36 秒(当数组的维度是在运行时计算时)。因此,性能恶化了两倍。
我希望现在一切都清楚了。非常感谢您的帮助。
【问题讨论】:
-
这应该与并行执行有什么关系?在串行执行中性能下降是否已经不可见?你多久分配一次?虚拟参数是否具有可分配属性?
-
您的问题不太可能与 mpi 相关。你是在做共享内存还是分布式内存?您可能遇到了内存瓶颈,但如果您做的一切都正确,则情况并非如此,因为代码的 COMMON 块版本可以正常工作。请包括您分配的方式和内容的示例代码。如果您分配和取消分配您的数组一次(分别是程序的开始和结束),您应该不会看到性能下降。
-
性能“糟糕”不是很量化,慢了多少?如上所述,请先在串行运行中验证您的问题。
-
伙计们,我很确定这个问题与并行编程或 MPI 无关。这就是为什么我的问题标题不包含与 MPI 相关的单词。我只是想准确并描述程序的环境。这是一个简单的例子,它说明了我在说什么(抱歉没有早点提供)找不到如何在评论中显示一段代码,所以我只在我的初始帖子中描述了这个例子
标签: performance memory-management fortran mpi fortran-common-block