用GCC和GFORTRAN实现矢量化

用GCC和GFORTRAN实现矢量化,gcc,compiler-optimization,avx,intel-fortran,avx2,Gcc,Compiler Optimization,Avx,Intel Fortran,Avx2,我有一个简单的循环,我希望在程序集中看到YMM寄存器,但我只看到XMM program loopunroll integer i double precision x(8) do i=1,8 x(i) = dble(i) + 5.0d0 enddo end program loopunroll 然后我编译它(gcc或gfortran不重要,我使用的是gcc 8.1.0) 但如果我这样做,英特尔并行工作室2018将更新3: [user@machine avx]$ ifort -S -mav

我有一个简单的循环,我希望在程序集中看到YMM寄存器,但我只看到XMM

program loopunroll
integer i
double precision x(8)
do i=1,8
   x(i) = dble(i) + 5.0d0
enddo
end program loopunroll
然后我编译它(gcc或gfortran不重要,我使用的是gcc 8.1.0)

但如果我这样做,英特尔并行工作室2018将更新3:

[user@machine avx]$ ifort -S -mavx loopunroll.f90
[user@machine avx]$ cat loopunroll.s|grep mm                                                 vmovdqu   .L_2il0floatpacket.0(%rip), %xmm2             #11.8
    vpaddd    .L_2il0floatpacket.2(%rip), %xmm2, %xmm3      #11.15
    vmovupd   .L_2il0floatpacket.1(%rip), %ymm4             #11.23
    vcvtdq2pd %xmm2, %ymm0                                  #11.15
    vcvtdq2pd %xmm3, %ymm5                                  #11.15
    vaddpd    %ymm0, %ymm4, %ymm1                           #11.8
    vaddpd    %ymm5, %ymm4, %ymm6                           #11.8
    vmovupd   %ymm1, loopunroll_$X.0.1(%rip)                #11.8
    vmovupd   %ymm6, 32+loopunroll_$X.0.1(%rip)             #11.8
我也试过旗子 -三月=core-avx2-mtune=core-avx2 对于gnu和intel,我在gnu生成的程序集中仍然得到了相同的XMM结果,但在intel生成的程序集中得到了YMM结果

我应该做些什么来取悦大家

非常感谢,,
M

您忘记使用
gfortran
启用优化。使用
gfortran-O3-march=native

为了不完全优化,请编写一个函数(子例程),该函数生成的结果在该子例程之外的代码可以看到。e、 g.将
x
作为参数并存储它。编译器必须发出适用于任何调用方的asm,包括调用子例程后关心数组内容的调用方


对于gcc,
-ftree vectorize
仅在
-O3
处启用,而不是在
-O2
处启用

gcc默认值为
-O0
,即编译速度快,生成速度慢得惊人的代码,从而提供一致的调试

gcc永远不会在
-O0
自动矢量化。必须使用
-O3
-O2-ftree矢量化

与gcc不同,
ifort
默认值显然包括优化。如果不对gcc使用
-O3
,则不应期望
ifort-S
gcc-S
的输出在远程相似


当我使用-O3时,它会在程序集中丢弃对XMM和YMM的任何引用

编译器优化无用的工作是件好事

编写一个函数,该函数接受数组输入arg并写入输出arg,然后查看asm中的该函数。或在两个全局数组上运行的函数。不是一个完整的程序,因为编译器有完整的程序优化

无论如何,请参阅以获取有关编写有用函数以查看编译器asm输出的提示。这是一个C问答,但所有的建议也适用于Fortran:编写接受参数并返回结果的函数,或者产生无法优化的副作用

没有Fortran,而且看起来
-xfortran
无法使
g++
编译为Fortran。(<代码> -XC< /COD>工作在C中代替C++编译为GOOBET)。否则,我建议使用该工具来查看编译器输出。< /P>
我制作了一个C版本的循环,以查看gcc对其优化器的类似输入做了什么。(我没有安装gfortran 8.1,也不太了解Fortran。我来这里是为了AVX和优化标签,但gfortran使用的后端与我非常熟悉的gcc相同。)

我们可以通过使用偏移量来阻止小数组的常量传播,因此要存储的值不再是编译时常量:

void store_i5_var(double *x, int offset) {
    for(int i=0 ; i<8; i++) {
        x[i] = 5.0 + (i + offset);
    }
}
void store_i5_var(双*x,整数偏移){

对于(int i=0;i您忘记使用
gfortran
启用优化。请使用
gfortran-O3-march=native

为了不完全优化,编写一个函数(子例程)这将产生子例程外部的代码可以看到的结果。例如,将
x
作为参数并存储它。编译器必须发出适用于任何调用方的asm,包括在调用子例程后关心数组内容的调用方


对于gcc,
-ftree vectorize
仅在
-O3
处启用,而不是在
-O2
处启用

gcc默认值为
-O0
,即编译速度快,生成速度慢得惊人的代码,从而提供一致的调试

gcc永远不会在
-O0
处自动矢量化。必须使用
-O3
-O2-ftree矢量化

与gcc不同,
ifort
默认值显然包括优化。如果不对gcc使用
-O3
,则不应期望
ifort-S
gcc-S
的输出非常相似


当我使用-O3时,它会在程序集中丢弃对XMM和YMM的任何引用

编译器优化无用的工作是件好事

编写一个函数,该函数接受数组输入arg并写入输出arg,然后查看asm中的该函数。或者是一个在两个全局数组上运行的函数。不是一个完整的程序,因为编译器具有完整的程序优化

无论如何,请参阅以获取编写有用函数以查看编译器asm输出的提示。这是一个C问答,但所有建议也适用于Fortran:编写接受参数并返回结果或具有无法优化的副作用的函数

不存在FORTRAN,它看起来像<代码> -Xfortran < /C> >不能使<代码> G++< /COD>编译为FORTRAN。(<代码> -XC< /COD>工作在C上编译为C++而不是GOOBD上的C++)。否则,我建议使用查看编译器输出的工具。< /P>


我制作了一个C版本的循环,看看gcc对其优化器的输入做了什么(我没有安装gfortran 8.1,也几乎不知道Fortran。我在这里是为了AVX和优化标签,但gfortran使用与gcc相同的后端,我非常熟悉)

我们可以通过使用偏移量来阻止小数组的常量传播,因此要存储的值不再是编译时常量:

void store_i5_var(double *x, int offset) {
    for(int i=0 ; i<8; i++) {
        x[i] = 5.0 + (i + offset);
    }
}
void store_i5_var(双*x,整数偏移){

对于(int i=0;i来说,为了整理这一点,Peters的建议是正确的。我的代码现在如下所示:

program loopunroll

double precision x(512)
call looptest(x)

end program loopunroll

subroutine looptest(x)
  integer i
  double precision x(512)
  do i=1,512
     x(i) = dble(i) + 5.0d0
  enddo
  return
end subroutine looptest
生产YMM的方法是

 gfortran -S  -march=haswell -O3 loopunroll.f90

为了整理一下,Peters的建议是正确的。我的代码现在看起来像:

program loopunroll

double precision x(512)
call looptest(x)

end program loopunroll

subroutine looptest(x)
  integer i
  double precision x(512)
  do i=1,512
     x(i) = dble(i) + 5.0d0
  enddo
  return
end subroutine looptest
生产YMM的方法是

 gfortran -S  -march=haswell -O3 loopunroll.f90

您忘记使用
gfortran
启用优化。请使用
gfortran-O3-march=native