Fortran分配/解除分配

时间:2012-07-04 20:27:41

标签: performance memory-management fortran

我有以下问题: Fortran90 +中分配/解除分配语句的实际开销是多少? 即,在循环内部分配了几个中型数组,如

do i = 1, 1000
    allocate(tmp(20))
    tmp(1:20) = 1d0
    call foo(tmp)
    deallocate(tmp)
end do 

在这种情况下,是否值得根据最大大小分配单个工作数组?

2 个答案:

答案 0 :(得分:7)

我发现紧密循环中的动态数组分配确实会减慢代码的执行速度,而valgrind显示mallocfree占用了大部分周期。因此,如果foo是一个非常快速的函数,那么静态分配这个数组是值得的。通过使用valgrind的callgrind功能进行性能分析很容易看出这种开销(由于配置文件的执行速度至少要慢10倍,因此可能值得减小问题的大小。)

在Fortran 2008中,对这类问题有一个更好的解决方案。您可以在block构造中声明变量,其大小在运行时确定。这应该使编译器更容易在堆栈上分配变量。但是我个人并没有使用它,我不确定哪个编译器支持它。

答案 1 :(得分:4)

使用ALLOCATEDEALLOCATE的开销与在C中使用malloc()free()的开销相同。实际上,大多数Fortran编译器实现(DE)ALLOCATE作为malloc()/free()周围的包装,增加了一些簿记功能,这是所有Fortran 90阵列所固有的。

通常最好预先分配足够大的临时数组并在紧密循环中使用它,而不是不断分配和释放内存。它还使堆不会碎片化,这可能导致以后的分配问题(非常罕见的情况,但它会发生,特别是对于32位代码)。