为什么打开gfortran编译器优化后matmul会变慢



如果我在Mac上使用gfortran (Homebrew GCC 8.2.0)编译下面的简单程序而不进行优化(-O0(,则对matmul的调用将在约90毫秒内持续执行。如果我使用任何优化(标志-O1-O2-O3(,执行时间将增加到~250毫秒。我已经尝试为inVectmatrix使用各种不同的大小,但在所有情况下,-O0选项都比其他三个优化标志好,至少是的2.5倍。如果我使用只有几百个元素的较小矩阵,但循环多次调用matmul,则性能会更差,接近10倍。

有什么办法可以避免这种行为吗?我需要在代码的某些部分使用优化,但同时,我也希望尽可能高效地执行矩阵乘法。

我使用命令gfortran -ON sandbox.f90编译包含以下代码的文件sandbox.f90,其中N是优化级别0-3(不使用其他编译器标志(。仅打印outVect的第一个值是为了防止gfortran优化过于巧妙并完全跳过对matmul的调用。

我是Fortran新手,所以如果我在这里遗漏了一些明显的东西,我会提前道歉。

program main
implicit none
real :: inVect(20000), matrix(20000,10000), outVect(10000)
real :: start, finish
call random_number(inVect)
call random_number(matrix)

call cpu_time(start)
outVect = matmul(inVect, matrix)
call cpu_time(finish)
print '("Time = ",f10.7," seconds. – First Value = ",f10.4)',finish-start,outVect(1)
end program main

首先,考虑一下我可能错了。我只是第一次看到这个问题,我和你一样感到惊讶。

我刚刚研究了这个问题,我理解如下。优化-O0O3Ofast和。。。是为大多数一般(常见(情况编写的。然而,在某些情况下(当-O3的效率低于-O*<-O3时(,优化会导致缺点。这是因为这些优化会隐式调用标志,从而降低特定任务的执行时间。对于您的情况,-O3强制所有matmul()函数都将内联。这样的事情通常是好的,但对于大数组或该函数的多次调用来说不是必须的。不知怎的,内联matmul()的成本比内联函数获得的增益更重要(至少我是这样认为的(。

为了避免这种行为,我建议使用标志-O3 -finline-matmul-limit=0来取消matmul函数的内联。使用标志CCD_ 26导致不比针对CCD_ 27获得的执行时间差的执行时间。

只有当涉及的数组小于n时,才能使用-finline-matmul-limit=n内联matmul函数。为了简单起见,我使用n=0

我希望这对你有帮助。

最新更新