用于omp simd的多维数组的对齐

Vla*_*r F 8 fortran simd openmp

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

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

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
Run Code Online (Sandbox Code Playgroud)

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

编译器如何使用该信息推断内部循环子阵列的对齐?

如果运行时尺寸更好(比如128,128,128),性能是否重要?

Ant*_*ama 1

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

你应该

1)对齐数组

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

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

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
Run Code Online (Sandbox Code Playgroud)

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

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