Optimization fortran 90(gfortran)是否优化了数组语法?
我在基于数组的解释语言方面做了很多工作,但我正在研究Fortran。在编写了第一段代码之后,我刚刚想到的问题是gfortran是否会通过将表达式放在单个循环中来使用数组语法优化表达式。在大多数基于数组的解释器中,诸如A=B/n*2*pi(其中B是数组)之类的表达式将需要5个循环和多个数组临时变量来计算。gfortran是否足够聪明,可以对此进行优化,我下面的代码(计算0到2pi数组的行)是否会像表达式周围的显式do循环一样高效?如果我担心性能,那么在使用数组语法时,有什么需要注意的吗Optimization fortran 90(gfortran)是否优化了数组语法?,optimization,gfortran,Optimization,Gfortran,我在基于数组的解释语言方面做了很多工作,但我正在研究Fortran。在编写了第一段代码之后,我刚刚想到的问题是gfortran是否会通过将表达式放在单个循环中来使用数组语法优化表达式。在大多数基于数组的解释器中,诸如A=B/n*2*pi(其中B是数组)之类的表达式将需要5个循环和多个数组临时变量来计算。gfortran是否足够聪明,可以对此进行优化,我下面的代码(计算0到2pi数组的行)是否会像表达式周围的显式do循环一样高效?如果我担心性能,那么在使用数组语法时,有什么需要注意的吗 PROGR
PROGRAM Sine
IMPLICIT NONE
REAL, PARAMETER :: PI = 3.415926535
INTEGER, PARAMETER :: z = 500
INTEGER :: ier
INTEGER, EXTERNAL :: PGBEG
REAL, DIMENSION(z) :: x,y
x=(indgen(z)-1.0)/z*(2*pi) ! This line...``
y=sin(x)
CALL plot(y,x)
CONTAINS
FUNCTION indgen(n) result(i)
INTEGER :: n
INTEGER, DIMENSION(n) :: i
INTEGER :: l
DO l=1,n
i(l)=l
END DO
END FUNCTION indgen
SUBROUTINE plot(y,x)
REAL, DIMENSION(:) :: x,y
ier=PGBEG(0,'/XWINDOW',1,1)
CALL PGENV(0.0,7.0,-1.0,1.0,0,1)
CALL PGLINE(SIZE(x),x,y)
CALL PGEND()
END SUBROUTINE plot
END PROGRAM Sine
对。
Fortran是编译的,而不是解释的。
它可以很好地处理循环。是的。
Fortran是编译的,而不是解释的。
它可以很好地处理循环。在gfortran中,您可以使用
-Warray temporaries
标志查看生成的所有数组temporaries。当我尝试您的示例时,不会生成额外的临时数组(除了存储indgen(z)结果所需的临时数组),因此我猜gfortran足够聪明 在gfortran中,您可以使用-Warray temporaries
标志查看生成的所有数组temporaries。当我尝试您的示例时,不会生成额外的临时数组(除了存储indgen(z)结果所需的临时数组),因此我猜gfortran足够聪明 表达式z*(2*pi)
是一个编译时常量,编译器可以很容易地验证它,因此无论如何,都不应该在运行时对其求值。此外,几乎所有现代编译器都应该在单个循环中执行一行“基本”数组操作,并且在许多情况下会生成SIMD指令(自动矢量化)
是否生成临时文件通常取决于每个元素是否可以独立处理,以及编译器是否能够证明这一点。朱晓蕾建议使用-Warray temporaries
,这是一个很好的建议。不要将它与-fcheck=array temp
混淆,我认为这只适用于为函数调用生成的临时值
下面是一个来自gfortran的消息示例:
foo.F90:4.12:
foo(1:20) = 2*foo(20:1:-1)
1
Warning: Creating array temporary at (1)
函数调用将在单独的循环中完成,除非编译器可以内联它。编译器是否内联一个短函数是很难预测的;这可能取决于其他函数的定义位置、函数是否具有pure
属性(尽管在实践中这似乎很少有关系)、编译器本身的供应商和版本以及传递的选项。一些编译器可以为此生成报告;我记得,英特尔编译器有一个不错的
编辑:也可以使用“隐含do循环”手动将表达式内联到这一行:
表达式z*(2*pi)
是一个编译时常量,编译器可以很容易地验证它,因此不管如何,都不应该在运行时对其求值。此外,几乎所有现代编译器都应该在单个循环中执行一行“基本”数组操作,并且在许多情况下会生成SIMD指令(自动矢量化)
是否生成临时文件通常取决于每个元素是否可以独立处理,以及编译器是否能够证明这一点。朱晓蕾建议使用-Warray temporaries
,这是一个很好的建议。不要将它与-fcheck=array temp
混淆,我认为这只适用于为函数调用生成的临时值
下面是一个来自gfortran的消息示例:
foo.F90:4.12:
foo(1:20) = 2*foo(20:1:-1)
1
Warning: Creating array temporary at (1)
函数调用将在单独的循环中完成,除非编译器可以内联它。编译器是否内联一个短函数是很难预测的;这可能取决于其他函数的定义位置、函数是否具有pure
属性(尽管在实践中这似乎很少有关系)、编译器本身的供应商和版本以及传递的选项。一些编译器可以为此生成报告;我记得,英特尔编译器有一个不错的
编辑:也可以使用“隐含do循环”手动将表达式内联到这一行:
谢谢,但这并不能回答我的问题。我不是问编译器是否比解释器更好地处理循环,我是想弄清楚它是否将表达式封装在一个循环中,而不是像在许多解释的数组语言中那样依次执行每个操作。再仔细想想,我猜我的代码至少被编译为2个循环;一个在indgen中,一个(或多个?)来评估表达式的其余部分。谢谢,但这并不能回答我的问题。我不是问编译器是否比解释器更好地处理循环,我是想弄清楚它是否将表达式封装在一个循环中,而不是像在许多解释的数组语言中那样依次执行每个操作。再仔细想想,我猜我的代码至少被编译为2个循环;一个位于indgen内部,一个(或多个?)用于计算表达式的其余部分。