如何在 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
快很多
我正在使用 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
快很多