如何在 Fortran 中实现数组结构而不是结构数组?

How to implement Structures of Arrays instead of Arrays of Structures in Fortran?

我正在使用 Fortran 编写有关 CFD 主题的代码。在与一些计算机科学的朋友讨论后,他们告诉我,如果在 his/her 代码上实现数组结构 (SoA) 而不是结构数组 (AoS),可以加快计算时间。

关于本主题的实现,我看到了很多示例,但其中大部分是使用 C 或 C++ 编写的。 (例如 https://software.intel.com/en-us/articles/how-to-manipulate-data-structure-to-optimize-memory-use-on-32-bit-intel-architecture)。

谁能告诉我或指导我一些基本的想法或示例如何在 Fortran 中实现 SoA 而不是 AoS?

这个概念真的没有什么难的。

而不是

type struct
  real x, y, z
end type

type(struct), allocatable :: array(:)

你用

type(struct2)
  real, dimension(:), allocatable :: x, y, z
end ype

type(struct2) :: arrays

它实际上只是对 C 或 C++ 示例的逐行翻译。或多或少,您可以阅读的有关该主题的所有内容仍然适用于 Fortran,即使他们使用其他语言作为示例。

实际上,在过去,Fortran 没有任何结构,最自然的方式就是声明变量:

real x(bigN)
real y(bigN)
real z(bigN)

并且您也可以通过这种方式获得数组结构的所有性能优势。对于 Fortranner 来说,有人只知道结构数组,这听起来很奇怪。

(100000,5) 效果一样好,因为 100000 是连续的。 我可能会这么明确地说,即:

!DIR$ ATTRIBUTES ALIGN:64                   :: A
REAL DIMENSION(:.:), ALLOCATABlE, CONTIGUOUS:: A

但该结构也有效。 取决于你喜欢什么。 当 5 是一个更大的数字以在 j (5) 循环上并行化,并在连续的 I (100000) 循环上向量化时,这似乎更直观(对我而言)。或做任务,或其他 !$OMP workshare 方法。

如果使用 A、B、C、D、E 而不是 1-5,实际上您不需要结构或数组...

"The Why"就是连续的数据可以向量化,因为是数组。 当它是一个结构数组时,您从一个值到下一个值绑定了 5,并且在任何一次聚集中都浪费了时间,或者无法对其进行矢量化,或者两者兼而有之。

然后在你的 I-loop (100000) 上,你要么自动矢量化,要么使用 OMP,要么使用 CilkPlus 外观语句 A(:) = ... 有时矢量符号与 OMP 和自动矢量化一样快,有时它比 OMP 慢。您需要尝试两种 (3) 方式,OMP 通常是可靠的,但多了几行且可读性较差。 它应该 运行 比 SoA

快很多