Fortran SWITCH 构建速度

Posted

技术标签:

【中文标题】Fortran SWITCH 构建速度【英文标题】:Fortran SWITCH construct speed 【发布时间】:2019-04-04 15:05:50 【问题描述】:

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

【问题讨论】:

从 F77 开始的 SWITCH 语句称为 SELECT CASE。由于您有 ELSE,因此您必须至少使用 F77,因为 F66 中也不存在。 我不知道 SELECT CASE。您知道(现在)三个选项中哪个更有效吗? 顺便说一句,我添加了fortran77标签 取决于编译器。猜测一下goto。为什么不尝试最后一个案例 10000 次,看看哪个更快? Select Case 实际上是在 Fortran 90 中进入 Fortran 的,所以才 25 年左右前... 【参考方案1】:

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

必填帖:GOTO still considered harmful?


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

计算的 GOTO 语句的执行导致标量整数表达式的计算。如果这个值是 i 使得 1 ≤ i ≤ n 其中 n 是 label-list 中标签的数量,分支发生到由列表中的 ith 标签标识的分支目标语句标签。 如果 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 f1,2,3.f90; do ifort -O3 -S $i; done
$ meld f1,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

【讨论】:

你说得对,在这种情况下编译器可以将 if 转换为 switch。差异只会在更复杂的情况下或没有优化的情况下出现。 如果“代码通过几条指令会更快”,这不是错误。这是一个特点!也就是说,它将产生相同(甚至几乎相同)的汇编代码这一事实是我们在添加到大型遗留程序时选择更具可读性的替代方案所需的全部理由。 @DanEckhart 你可以称它为一个特性,但我想说的是这两个代码的行为不同,如果WHICH 小于 1,GOTO 代码也将运行第一种情况或大于 3。IF 代码不这样做。它是一个错误吗?如果WHICH 可以出于任何原因拥有这些值,则可能是一个错误。它是一个功能吗?如果您 100% 确定 WHICH 仅具有值 1、2 或 3,并且在此决策树的点上永远不会有其他值,则这是一项功能。 我只是在开玩笑。关于错过 WHICH

以上是关于Fortran SWITCH 构建速度的主要内容,如果未能解决你的问题,请参考以下文章

如何提高 Makefile 的速度?

Matlab 与 Julia 与 Fortran 中的速度

为啥 C 语言不支持列主数组? [关闭]

[转载:]C#与Fortran混合编程之本地调用Fortran动态链接库

HDF5:构建 Fortran 库 (Windows)

fortran 中的combinations_with_replacement 函数?