Fortran中的矢量化和

drj*_*rm3 7 fortran sse simd gfortran avx

我正在Fortran使用gfortran和编译我的代码,-mavx并且已经验证了一些指令是通过矢量化的objdump,但是我没有得到我期望的速度改进,所以我想确保以下参数被矢量化(这条指令是~50运行时的百分比).

我知道一些指令可以被矢量化,而其他指令则不能,所以我想确保它可以是:

sum(A(i1:i2,ir))

同样,这条单行占用了大约50%的运行时间,因为我在非常大的矩阵上执行此操作.我可以提供更多有关我为什么要这样做的信息,但只要说它是必要的,尽管我可以在必要时重构内存(例如,我可以做总和,sum(A(ir,i1:i2))好像它可以被矢量化.

这条线是矢量化的吗?我该怎么说?如果不进行矢量化,如何强制进行矢量化?

编辑:感谢评论,我现在意识到我可以检查此求和的矢量化,-ftree-vectorizer-verbose并看到这不是矢量化.我重新编写了如下代码:

tsum = 0.0d0
tn = i2 - i1 + 1
tvec(1:tn) = A(i1:i2, ir)
do ii = 1,tn
    tsum = tsum + tvec(ii)
enddo
Run Code Online (Sandbox Code Playgroud)

当我打开时,这只能进行矢量化-funsafe-math-optimizations,但我确实看到由于矢量化而增加了70%的速度.问题仍然存在:为什么不进行sum(A(i1:i2,ir))矢量化,如何进行简单sum的矢量化?

drj*_*rm3 1

-ffast-math事实证明,除非我包含or ,否则我无法使用矢量化-funsafe-math-optimizations

我使用的两个代码片段是:

tsum = 0.0d0
tvec(1:n) = A(i1:i2, ir)
do ii = 1,n
    tsum = tsum + tvec(ii)
enddo
Run Code Online (Sandbox Code Playgroud)

tsum = sum(A(i1:i2,ir))
Run Code Online (Sandbox Code Playgroud)

以下是使用不同编译选项运行第一个代码片段时的时间:

10.62 sec ... None
10.35 sec ... -mtune=native -mavx
 7.44 sec ... -mtune-native -mavx -ffast-math
 7.49 sec ... -mtune-native -mavx -funsafe-math-optimizations
Run Code Online (Sandbox Code Playgroud)

最后,通过这些相同的优化,我能够向量化tsum = sum(A(i1:i2,ir))以获得

 7.96 sec ... None
 8.41 sec ... -mtune=native -mavx
 5.06 sec ... -mtune=native -mavx -ffast-math
 4.97 sec ... -mtune=native -mavx -funsafe-math-optimizations
Run Code Online (Sandbox Code Playgroud)

当我们将sum-mtune=native -mavx与进行比较时-mtune=native -mavx -funsafe-math-optimizations,它显示出约 70% 的加速。(请注意,这些仅运行一次 - 在我们发布之前,我们将对多次运行进行真正的基准测试)。

不过我确实受到了一点打击。当我使用这些-f选项时,我的价值观会略有变化。v1如果没有它们,我的变量 ( , )的错误v2是:

v1 ... 5.60663e-15     9.71445e-17     1.05471e-15
v2 ... 5.11674e-14     1.79301e-14     2.58127e-15
Run Code Online (Sandbox Code Playgroud)

但通过优化,错误是:

v1 ... 7.11931e-15     5.39846e-15     3.33067e-16
v2 ... 1.97273e-13     6.98608e-14     2.17742e-14
Run Code Online (Sandbox Code Playgroud)

这表明确实发生了一些不同的事情。