【问题标题】:Alignment of multi-dimensional array for omp simdomp simd的多维数组对齐
【发布时间】:2016-01-27 03:05:28
【问题描述】:

如果我理解omp simd 构造的aligned 子句,它指的是整个数组的对齐方式。

它如何用于多维数组?假设

ni = 131; nj = 137; nk = 127

!allocates  arr(1:131,1:137,1:127) aligned to 64-bytes
call somehow_allocate_aligned(arr, [ni,nj,nk], 64)

!$omp parallel do collapse(2)
do k = 1, nk
  do j = 1, nj

    call some_complicated_subroutine(arr(:,j,k))

    !$omp simd aligned(arr:64)
    do i = 1, ni
      arr(i,j,k) = some arithmetic expression involving arr(i,j,k)
    end do
  end do
end do
!$omp end parallel do

尽管内部循环的迭代从arr(1,j,k) 开始,但这是指示数组对齐的正确方法吗?

编译器如何使用该信息来推断有关内部循环子数组的对齐方式?

如果运行时大小更好(比如 128、128、128)对性能有影响吗?

【问题讨论】:

  • 因为您仅沿 i 轴执行 SIMD 矢量化,您只需将您的 arr 数组与该维度中的 64 字节对齐。其他维度可以是任意长度,它根本不应该影响您的矢量化。您始终可以通过查看使用-qopenmp-simd -qopt-report=5 编译的输出来仔细检查您设置的对齐方式和执行的矢量化是否一致。
  • @NoseKnowsAll Fortran 数组不能那样工作(沿一维对齐)。它们是连续的。哪个编译器支持您引用的选项?
  • 是的,Fortran 数组是连续的。但是在您的情况下,simd 构造仅沿 1 个轴工作,因此对于该构造,您基本上是将数组的一维切片交给它。该切片是唯一必须对齐的部分。 (另外,将最快的维度自动对齐到 64 字节意味着 3D 数组无论如何都会对齐到 64 字节......)是的,这些都是 ifort 选项。
  • 我的意思是,arr(:,2,1)arr 的对齐方式(可以)不同。可以通过在 FORTRAN77 样式中分配更大的数组来避免这种情况,但这会给代码的其他部分带来大量挑战。
  • 即使数组的大小恰好使得连续的部分(列?)以相同的方式对齐,编译器是否能够知道这一点?我如何告诉它这些信息?

标签: fortran openmp simd


【解决方案1】:

这里有解释,幻灯片 160-165:http://irpf90.ups-tlse.fr/files/parallel_programming.pdf

你应该

1) 对齐数组

2) 使用填充强制所有列对齐:您的第一个维度(在 allocate 语句中指定)应该是元素数量的倍数,以达到 16、32 或 64 字节边界,具体取决于指令设置。

例如,对于一个 99x29x200 矩阵,其 AVX 指令集(32 字节对齐)为双精度(8 字节/元素),您应该这样做

n = 99
l = 29
m=200

delta_n = mod(n,32/8)
if (delta_n == 0) then
  n_pad = n
else
  n_pad = n-delta_n+32/8
end if

allocate( A(n_pad,l,m) )
!DIR$ ATTRIBUTES ALIGN : 32 :: A

do k=1,m
  do j=1,l
    !$OMP SIMD
    do i=1,n
      A(i,j,k) = ...
    end do
  end do
end do

您可以使用 C 预处理器制作可移植代码,替换前面示例中的 32 和 8。

注意:对数组使用诸如 B=A 之类的语句时要小心,因为物理维度与逻辑维度不对应。好的做法是将边界设置为 B(1:n,1:l,1:m) = A(1:n,1:l,1:m),因为如果您更改物理尺寸,它仍然可以工作。

【讨论】:

  • 该参考似乎没有考虑 OpenMP simd 构造。 ATTRIBUTES ALIGN 指令类似,但我不知道它是否保证具有相同的语义。此外,并不是我所有的编译器都知道这个指令。问题也是,即使我努力并对齐列(这会导致其他地方出现问题),编译器是否会知道并使用列对齐的知识?我如何告诉编译器?
  • !DIR$ 指令是 Intel 特定的。它们似乎比用于矢量化的!$OMP SIMD 更成熟:software.intel.com/en-us/forums/… 您可以使用!$OMP SIMD aligned(A) 告诉编译器数组已经对齐。编译器将利用对齐,但如果数组未对齐,您可能会遇到分段错误。但是,我找不到如何告诉 gfortran 对齐数组....
  • 我总是可以从对memalign的调用中创建一个指针数组,这不是什么大问题。
  • 确实如此,所以在这种情况下它应该可以工作。您可以尝试编写一个包含矢量化循环的小测试,使用-g 选项对其进行编译,并检查循环是否在生成的汇编代码中进行了矢量化(objdump -d test.o)。
  • 或者干脆用-S编译并享受带注释的汇编输出。
猜你喜欢
  • 2021-04-04
  • 2016-05-03
  • 1970-01-01
  • 1970-01-01
  • 2018-07-20
  • 2016-10-04
  • 2021-04-09
  • 2021-10-24
  • 1970-01-01
相关资源
最近更新 更多