【问题标题】:Implicit allocation by assignment vs explicit allocation/deallocation隐式分配与显式分配/解除分配
【发布时间】:2019-02-04 22:17:21
【问题描述】:

如果我的编译器兼容 Fortran 2003,我可以重新分配可分配变量或数组,而无需像 Automatic array allocation upon assignment in Fortran 中所述的显式解除/分配过程。例如

integer, allocatable :: i(:)

i = [1,2,3]
i = [1,2,3,4,5]

与旧的(Fortran 90)方式:

if( allocated(i) ) deallocate(i)
allocate(i(3))
i = [1,2,3]
if( allocated(i) ) deallocate(i)
allocate(i(5))
i = [1,2,3,4,5]

这种新技术有什么优点和缺点?它肯定比旧方法更简洁的代码。但是有理由更喜欢旧方式吗?我仍然在代码示例中看到旧方式比新方式更多,但这可能只是因为 Fortran 90 仍然比 Fortran 2003 使用更多。

作为一个快速的时间检查,我在 gfortran 4.8.5 下循环了上面的代码 100,000,000 次,发现新的方式似乎也更快,运行大约 4 秒(新方式)与 6 秒(旧方式)。相反,在@roygvib 下面的 cmets 中,与 gfortran 8.2 的结果基本相反。

另外,请注意这里最近对该问题的讨论:Fortran Discussion Group

【问题讨论】:

  • 在欺骗问题中,请参阅右侧的 Linked 以了解更多类似问题。
  • 在这种情况下,您应该以明确与非重复方面有关的方式编写问题,而不是添加仍然留下其他地方解释的那些点的编辑,重新编写问题!好的,我为你做了...
  • 其他问题似乎围绕“我有一个错误”的主题展开,而这个问题涉及两种编程风格之间的比较。
  • @JohnE 没有什么可以阻止您完善问题,阻止您在关闭或“暂停”时完善问题。恰恰相反,关闭消息通常明确地包含如何重新打开它的指令。唉,我自己做了这样的编辑,然后重新打开了你的问题。
  • 我刚刚尝试比较上述两种模式的 10^8 循环,但使用 gfortran-8.2 -O3 的第二个版本更快(约 40%)。另一方面,有点旧的 PGI fortran 给出了基本相同的时间。所以结果可能会因编译器而异?

标签: fortran


【解决方案1】:

我会列出差异,优点或缺点是主观的。

编译器必须检查每个整个数组分配的正确边界——但这无论如何都必须发生,即使您不使用重新分配。除非您在某些编译器中完全禁用此标准功能。

对于那些不习惯动态语言的人来说,大多数赋值都会进行一些分配,这可能是一个重要的事实,即在 deallocatereallocate 语句中,重新分配实际上正在发生。

通过自动重新分配,编译器可能会使用realloc,尤其是在a = [a, 1] 这样的情况下。但据我所知,编译器目前不这样做。尽管如此,通常的malloc 经常会重新使用旧数组所在的内存,如果它适合那里的话。

【讨论】:

    【解决方案2】:

    优点是代码简洁。

    integer, allocatable :: i(:)
    
    i = [1, 2, 3]
    

    少一行

    integer, allocatable :: i(:)
    
    allocate(i(3))
    i = [1, 2, 3]
    

    另外,你不需要明确写出分配的大小,所以冗余信息少了一点。

    不方便的是它是一个自动功能。

    我可以很容易地想到该功能是劣势的两种情况。

    1. 数组 i 在分配时被重新分配是有充分理由的(即不是代码中的错误),并引入了可能更难找到的性能损失。
    2. 由于代码中的逻辑错误,数组i 被重新分配。这个错误会更容易检测到,因为随之而来的越界内存访问引发了段错误:-)

    不过,您可能会通过编译器检查检测“2”并使用探查器解决“1”。所以,除非你有很好的理由不使用该功能,否则我会说“使用它”。然而,对于现有的代码库,没有“仅仅因为”删除分配语句的具体动机。

    【讨论】:

    • 你几乎总是需要一行if(allocated(foo)) deallocate(foo),除非你知道你将准确分配一次,即使这样包含它也更安全。所以通常它是 2 额外的行而不是 1。
    • 我考虑过单次分配,但当然对于变量的重新分配,您需要更多的逻辑。
    猜你喜欢
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多