【发布时间】:2021-03-17 22:30:10
【问题描述】:
如果我在我的 Mac 上使用 gfortran (Homebrew 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会更快的原因。但是,您可以尝试使用 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)上使用了相当基本的设置(无 VM)。
标签: optimization fortran matrix-multiplication gfortran