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