【问题标题】:speed of procedure functions versus subroutines程序函数与子程序的速度
【发布时间】:2013-04-29 16:14:31
【问题描述】:

Fortran 中 OOP 特性的标准是它们有利于可读性和重用性,但不利于执行时间。我在测试时得到的结果好坏参半。

我编写了一个简单的虚拟程序来测试这一点,方法是在派生类型中添加两​​个大数组。

type oop
  real(8),allocatable,dimension(:,:,:) :: array
contains
  procedure :: plusOOP,eqPlus
  generic   :: operator(+) => plusOOP
end type
type(oop) function plusOOP(a,b) result(c)
  class(oop),intent(in) :: a,b
  c%array = a%array+b%array
end function plusOOP
subroutine eqPlus(c,a,b)
  class(oop),intent(in)    :: a,b
  class(oop),intent(inout) :: c
  c%array = a%array+b%array
end subroutine eqPlus

我发现call c%eqPlus(a,b) 与添加标准数组一样快。然而,这似乎比写c%array = a%array+b%array 更清楚。不幸的是,c=a+b 对于值超过 1M 的数组来说要慢两倍左右。 (对于值小于 500K 的数组,c=a+b 的速度一样快,但这可能取决于特定的计算机。)

OOP 风格的真正问题是倾向于将所有内容编写为函数而不是子例程吗?有没有办法让c=a+b 没有大型数组的这种开销?

【问题讨论】:

  • 它将很大程度上依赖于处理器。您是否也尝试直接调用该函数?如今,编译器作者专注于如何实现这些东西以可靠地工作,而不是速度。理论上它应该能够将两者优化为相同的机器代码,但它不是我们现在所拥有的。
  • 是的,我试过了,还有很多其他排列不健康——同样的因素更慢。不过,我不会抱怨可靠性。

标签: oop fortran fortran2003


【解决方案1】:

如果你考虑一下,使用函数会慢很多,因为

  1. 必须为返回值分配内存
  2. 函数返回时,必须将数据复制到接收变量中
  3. 必须丢弃临时内存。

调用子程序时,只需将结果直接写入输出变量即可。

OOP 风格并不是要在函数中编写所有内容:这只是为了方便,以便阅读代码的人可以更轻松地理解它。 OOP 更多的是关于对象拥有数据并负责管理自己的数据。

【讨论】:

  • 编译器通常可以优化这个差异。
  • 我怀疑编译器的优化,尤其是返回巨大数组或结构的函数,因为在 C++、C#、Java 和 Delphi 中会遇到完全相同的性能问题。
  • 供参考,这些标准优化是stackoverflow.com/questions/12953127/…
猜你喜欢
  • 1970-01-01
  • 2018-09-11
  • 1970-01-01
  • 2012-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
相关资源
最近更新 更多