gfortran 编译器的强制向量化
Posted
技术标签:
【中文标题】gfortran 编译器的强制向量化【英文标题】:Mandated vectorization for gfortran compiler 【发布时间】:2015-07-21 09:34:15 【问题描述】:我想用矢量处理器(英特尔至强)以矢量方式执行 Fortran 循环。我最近用英特尔编译器实现了这一点,我们可以在循环之前添加!DIR$ SIMD
。
但是当我使用 gfortran 编译器时,我发现所有的向量化操作都是自动的。例如,
PROGRAM MAIN1
IMPLICIT NONE
DOUBLE PRECISION :: X(100)
INTEGER :: NELEM = 100, NELMAX = 100, LV = 4
INTEGER :: IKLE(100), I, IB, IELEM
DOUBLE PRECISION :: W(100)
DOUBLE PRECISION :: MASKEL(100)
LOGICAL :: MSK = .FALSE.
DO I = 1, 100
X(I) = I
IKLE(I) = I
W(I) = 0
END DO
DO IB = 1,(NELEM+LV-1)/LV
!------------loop to vectorize------------------
DO IELEM = 1+(IB-1)*LV , MIN(NELEM,IB*LV)
X(IKLE(IELEM)) = X(IKLE(IELEM)) + W(IELEM)
ENDDO ! IELEM
!-----------------------------------------------
ENDDO ! IB
PRINT *, X
END PROGRAM
gfortran main1.f -O3 -fopt-info-optimized
的部分输出打印在下面
main1.f:18:0: note: not vectorized: not suitable for gather load _33 = x[_32];
main1.f:18:0: note: bad data references.
main1.f:18:0: note: not vectorized: not enough data-refs in basic block.
main1.f:18:0: note: not vectorized: not enough data-refs in basic block.
由于ifort在强制向量化模式下编译循环时程序输出X是正确的,不知道gfortran是否也有类似的方式。
【问题讨论】:
你能摆脱 IKLE(IELEM) 吗?我知道没有这样的 gfortran 指令。您可能需要 OpenMP 4.0 中的 SIMD 指令。我通常不会将英特尔处理器称为“矢量”。 是的,我也这样做了,发现它有效。但不幸的是我无法摆脱它,这是计算的一部分。 你确定你有使用 ifort 的加速吗?如果你要求它,它甚至会向量化那些无法被向量化的循环。 也许不在这个演示中。但它可能在另一个更大的地方有用 不清楚向量化是否会加速这个循环:代码的算术强度很低,所以它似乎受内存限制。此外,如果可以的话,在 W 上进行随机读取而不是在 X 上进行随机写入可能是有利可图的。 【参考方案1】:在这种分散存储的情况下,当索引数组 IKLE(:) 中有重复条目时,通过指令强制矢量化可能会改变结果,因为它不会保留内存访问的顺序。据我所知,gfortran 中唯一可用的这种性质的指令是 !$omp simd,gfortran 可以随意忽略它。 omp simd 指令仅在设置了相应的编译选项时才有效。 ifort 提供(最新版本中的 -opt-report4)评估可能通过矢量化实现的峰值加速。我不知道该评估是否基于声明的数组大小。如果有加速,那么通过改变操作顺序比通过实际的 SIMD 并行更能实现。
【讨论】:
ifort 和 gfortran 生成的指令序列确实保留了存储的顺序,以防重复。在 avx512 中有冲突解决说明,以备不时之需。以上是关于gfortran 编译器的强制向量化的主要内容,如果未能解决你的问题,请参考以下文章