Sun Studio 12:Fortran 编程指南

9.1.4 消除性能抑制因素

使用 Sun Studio 性能分析器可确定程序的关键计算部分。 然后仔细分析循环或循环嵌套,消除有可能抑制优化器生成优化代码或者不然会降低性能的编码。有许多影响可移植性的非标准编码习惯也可能会抑制编译器的优化。

本章最后所列的某些参考书籍更为详细地论述了用于提高性能的重编程技巧。有三种主要方法值得在此提出:

9.1.4.1 删除关键循环中的 I/O

包含程序主要计算工作的循环或循环嵌套中的 I/O 会严重降低性能。花在 I/O 库上的 CPU 时间数量可能构成了循环所用时间的主要部分。(I/O 还会引起进程中断,因而降低程序处理能力。)尽可能将 I/O 移出计算循环,可以大大减少 I/O 库的调用次数。

9.1.4.2 消除子程序调用

循环嵌套深层调用的子程序可能会被调用数千次。即使每次调用花在每个例程上的时间很少,但累加效果却可能会很大。另外,由于编译器在调用期间不能对寄存器状态作出假设,所以子程序调用会抑制包含这些调用的循环的优化。

子程序调用的自动内联(使用 -inline=x,y,..z-O4)是一种让编译器用子程序本身替换实际调用的方法(即将子程序拉到循环中)。要内联的例程的子程序源代码必须与调用例程存在于相同的文件中。

还有其他几种消除子程序调用的方法:

9.1.4.3 合理化杂乱代码

计算密集型循环内的复杂条件操作对编译器进行的优化尝试具有很强的抑制作用。一般而言,消除所有算术和逻辑 IF 操作而代之以块 IF 操作是一条很好的规则,应予以遵守:


Original Code:
    IF(A(I)-DELTA) 10,10,11
10  XA(I) = XB(I)*B(I,I)
    XY(I) = XA(I) - A(I)
    GOTO 13
11  XA(I) = Z(I)
    XY(I) = Z(I)
    IF(QZDATA.LT.0.) GOTO 12
    ICNT = ICNT + 1
    ROX(ICNT) = XA(I)-DELTA/2.
12  SUM = SUM + X(I)
13  SUM = SUM + XA(I)

Untangled Code:
    IF(A(I).LE.DELTA) THEN
      XA(I) = XB(I)*B(I,I)
      XY(I) = XA(I) - A(I)
    ELSE
      XA(I) = Z(I)
      XY(I) = Z(I)
      IF(QZDATA.GE.0.) THEN
        ICNT = ICNT + 1
        ROX(ICNT) = XA(I)-DELTA/2.
      ENDIF
      SUM = SUM + X(I)
    ENDIF
    SUM = SUM + XA(I)

使用块 IF 不仅可以提高编译器生成优化代码的机会,而且可以增强可读性并确保可移植性。