高效的 CFD 编程技术

计算科学 流体动力学 表现 正则
2021-12-23 13:35:31

我正在尝试制作高效的 CFD 编程复杂性来解决燃烧问题。我已经写完了实现数学模型的core,现在我关心的是代码性能。燃烧问题在计算上非常昂贵,毫无疑问我必须对我的代码进行并行化,但现在我想制作高效的串行代码,将其用作并行程序的基础。

例如,程序中有一个简化版本:

我有时间循环所在的主程序。

PROGRAM Flame
USE Geometry
CALL ALLOCATION  <- Procedure there memory is allocated for X array
DO while ...
Time=Time + TH
CALL CALCULATIONS
END DO 
END PROGRAM

具有所有全局变量声明的模块

MODULE Geometry
double precision , allocatable :: X(:) <-- one dimensional array for computational grid.
integer, dimension(NTR) :: KDIF <-- has a mean of pointers on some variable in cell (pressure for example)
END MODULE

用于计算和数据处理的子程序。

SUBROUTINE CALCULATIONS
USE Geometry
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
IJK = 0
DO I=1,NX <- number of cells in one dimension (such cycles for all dimensions) 
  DO I1=1,NTR
    X(IJK+KDIF(I1)) = ... some floating-point operations <-- Possible hot spot
    I1 = I1+1
  END DO
  X(IJK+8)=X(IJK+3)-A/X(IJ+5)-(X(IJ+10)-B)*C/(D*X(IJ+5)) (for example)
IJK = IJK + NKX  <-- place between two cells in 
END DO
END SUBROUTINE

程序中有更多的子程序和模块,但它们的结构都与我举的例子相似。我尝试使用 VTune Amplifier 分析我的程序,并在我在代码中指出的地方找到了一些热点。在Assembly这样的热点中,最耗时的操作一般都是moved qword;移动 ebx, dword; 等我不熟悉汇编代码,但我认为它与内存操作有关。其实我不知道如何解决这些热点。

所以有一些问题我需要澄清。这种编码风格是现代的吗?我的意思是也许我应该对此类程序使用另一种技术,例如指针、FORALL 和 WHERE 操作,它们可以更快、更节省内存、更适合 CFD 问题?这样的程序结构是否有效(数据模块、子程序、可分配数组、一维数组甚至对于多维问题)?

提前感谢您的关注、回答和建议。

1个回答

优化代码是一个非常广泛的问题。在深入了解实现的细节之前,您应该确保您的模型和算法尽可能高效地执行您希望它们执行的操作。好的算法胜于好的实现,过早的优化是万恶之源。

说了这么多,以下是对您给出的代码的一些评论:

  • 永远不要使用隐式类型;它将拼写错误变成错误。
  • 对于forall、where等众说纷纭, 这个讨论特别有意思。总结:forall、where 等并没有提供太多(如果有的话)速度,但它们可以很好地表示算法。
  • 不要将数组切片作为参数传递;它们可能导致意外的临时分配和复制。
  • 可分配的很好;仅在需要更多功能时才切换到指针
  • 模块很好。我个人喜欢为几乎是参数(和例程)的参数或变量保留模块,并明确地移动数据。Fortran 是通过引用传递的,因此大数组参数并不比缩放器贵。我已经看到成功的代码可以做到这一点。