Fortran SWITCH构建速度

时间:2019-04-04 15:05:50

标签: fortran fortran77

我知道计算机科学通常对GOTO语句不满意,但是通过使用它可以获得速度上的优势

    INTEGER WHICH
    GOTO(100,200,300) WHICH
100 do something
    GOTO 400
200 do something else
    GOTO 400
300 do a third thing
    GOTO 400
400 CONTINUE

    INTEGER WHICH
    IF(WHICH.EQ.1)THEN
      do something
    ELSEIF(WHICH.EQ.2)THEN
      do something else
    ELSEIF(WHICH.EQ.3)THEN
      do a third thing
    ENDIF

因为Fortran缺少SWITCH语句?

1 个答案:

答案 0 :(得分:2)

首先,作为一般性评论,这类微优化确实不值得您花费时间。问题的答案更为重要:什么更易于调试,理解和迁移?

必填项:GOTO still considered harmful?

enter image description here


话虽如此,不幸的是,我必须通知您OP的代码示例中有一个错误(猛禽在这里)。您使用的计算出的GOTO语句具有以下属性:

  

执行已计算的GOTO语句将导致对标量整数表达式进行求值。如果此值为 i ,使得 1≤i≤n   其中 n 是label-list中的标签数,分支到由列表中 i th 标签标识的分支目标语句标签。 如果 i 小于 1 或大于 n ,则执行顺序将继续,就像执行了CONTINUE语句一样。

     

来源:Fortran 2008 Standard

这意味着正确的版本应为:

    INTEGER WHICH
    GOTO(100,200,300) WHICH
    GOTO 400                  << missing part
100 do something
    GOTO 400
200 do something else
    GOTO 400
300 do a third thing
    GOTO 400
400 CONTINUE

当生成以下3个文件的汇编代码(见下文)时,您实际上会注意到在优化下汇编代码是相同的。您可以使用bash脚本中的以下几行来快速检查自己:

$ for i in f{1,2,3}.f90; do ifort -O3 -S $i; done
$ meld f{1,2,3}.s

您还将注意到,如果删除了缺少的goto 400,则通过一些说明,goto汇编代码将更快。


f1.f90的来源:

subroutine g(a)
  integer a
  goto(100,200,300) a
  goto 400
100 call f1()
  goto 400
200 call f2()
  goto 400
300 call f3()
  goto 400
400 continue
end subroutine g

f2.f90的来源:

subroutine g(a)
  integer a
  if(a.eq.1)then
     call f1()
  elseif(a.eq.2)then
     call f2()
  elseif(a.eq.3)then
     call f3()
  endif
end subroutine g

f3.f90的来源:

subroutine g(a)
  integer a
  select case (a)
  case (1)
     call f1()
  case (2)
     call f2()
  case (3)
     call f3()
  end select
end subroutine g