Fortran SWITCH构建速度

Fortran SWITCH construct speed

我知道计算机科学通常不赞成 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 语句?

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

必填项post:GOTO still considered harmful?


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

Execution of a computed GOTO statement causes evaluation of the scalar integer expression. If this value is i such that 1 ≤ i ≤ n where n is the number of labels in label-list, a branch occurs to the branch target statement identified by the ith label in the list of labels. If i is less than 1 or greater than n, the execution sequence continues as though a CONTINUE statement were executed.

source: 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