我有以下问题:Fortran90+ 中分配/解除分配语句的实际开销是多少?即,在一个循环内分配了几个中等大小的数组,比如
do i = 1, 1000
allocate(tmp(20))
tmp(1:20) = 1d0
call foo(tmp)
deallocate(tmp)
end do
在这种情况下,是否值得根据最大大小分配单个工作数组?
我有以下问题:Fortran90+ 中分配/解除分配语句的实际开销是多少?即,在一个循环内分配了几个中等大小的数组,比如
do i = 1, 1000
allocate(tmp(20))
tmp(1:20) = 1d0
call foo(tmp)
deallocate(tmp)
end do
在这种情况下,是否值得根据最大大小分配单个工作数组?
我发现紧密循环中的动态数组分配确实会减慢代码的执行速度,而 valgrind 显示很大比例的循环被malloc
and占用free
。所以如果foo
是一个非常快速的函数,那么静态分配这个数组是值得的。通过使用valgrind的 callgrind 功能进行分析,很容易看到这种开销(可能值得减少问题的大小,因为分析的执行速度可能至少慢 10 倍)。
在 fortran 2008 中,此类问题有更好的解决方案。您可以在block
结构中声明变量,其大小在运行时确定。这应该使编译器更容易在堆栈上分配变量。但是我没有亲自使用过它,我不确定哪些编译器支持它。
使用and 的开销与在 C 中使用 andALLOCATE
的DEALLOCATE
开销相同。实际上,大多数 Fortran 编译器都将其实现为包装器,并增加了一些记录,这是所有 Fortran 90 数组所固有的。malloc()
free()
(DE)ALLOCATE
malloc()/free()
通常最好预先分配一个足够大的临时数组并在紧密循环中使用它,而不是不断地分配和释放内存。它还可以防止堆碎片化,这可能会导致稍后出现分配问题(非常罕见的情况,但它会发生,尤其是对于 32 位代码)。