Optimization 为什么启用gfortran编译器优化后matmul会变慢?

Optimization 为什么启用gfortran编译器优化后matmul会变慢?,optimization,fortran,matrix-multiplication,gfortran,Optimization,Fortran,Matrix Multiplication,Gfortran,如果我在Mac电脑上使用gfortran(自制GCC 8.2.0)编译下面的简单程序而不进行优化(-O0),则对matmul的调用将在约90毫秒内持续执行。如果我使用任何优化(标志-O1、-O2或-O3),执行时间将增加到约250毫秒。我曾尝试对inVect和matrix使用各种不同的大小,但在所有情况下,-O0选项的性能至少比其他三个优化标志高出2.5倍。如果我使用只有几百个元素的较小矩阵,但循环多次调用matmul,则性能损失更大,接近10倍 有没有办法避免这种行为?我需要在代码的某些部分使

如果我在Mac电脑上使用
gfortran(自制GCC 8.2.0)
编译下面的简单程序而不进行优化(
-O0
),则对
matmul
的调用将在约90毫秒内持续执行。如果我使用任何优化(标志
-O1
-O2
-O3
),执行时间将增加到约250毫秒。我曾尝试对
inVect
matrix
使用各种不同的大小,但在所有情况下,
-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

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


我刚刚研究了这个问题,我的理解如下。优化
-O0
O3
的AST
和。。。适用于大多数一般(常见)情况。但是,在某些情况下(当
-O3
的效率低于
-O*时,
-O0
会更快,我真的看不出原因。但是,您可以尝试使用BLAS进行矩阵向量乘法,并检查其执行情况(
sgemv
dgemv
应该为您这样做)。要查看引擎盖下发生了什么,您可以尝试汇编输出(
gfortran-s-o sandbox.asm sandbox.f90-on
)并对它们进行比较。非常奇怪。这种计算应该主要受内存带宽的限制。您是否使用M1处理器?虚拟机?简单的答案是,gfortran与MATMUL严重冲突(以及可能的其他内在程序)因为它的前端优化过程。我不会用细节来取悦你。你需要提交一份错误报告。@steve我不认为gfortran在MATMUL或其他内在过程中是如此的失败。据我所知,gfortran是一个做得非常好的产品。但是,因为它接近机器硬件(与其他语言相比),有时特定行为背后的原因并非微不足道。@JérômeRichard我在2017 MacBook Air(1.8 GHz双核Intel Core i5;8 GB 1600 MHz DDR3;macOS Catalina)上使用的是相当基本的设置(没有虚拟机).finline matmul limit=0
标志似乎在我测试过的所有情况下都能解决这个问题,包括对matmul的多次调用的循环导致了最大的减速。内联如何在这样一个简单的程序中产生10倍的减速对我来说是个谜,但我很高兴有一个解决方案。谢谢r我也是。但是,我没有更好的解释。这个问题只影响向量矩阵乘法。正在准备修复。在这种情况下,直接联系gfortran开发人员是明智的,而不是希望有人为你做这件事。@steve感谢你在留言板上添加这篇帖子。我真的不是c完全确定这个问题不是用户错误(正如我所说,我是一个Fortran新手),所以我决定先在这里发布。在将来,我会直接联系开发人员。