2012-07-04 87 views
7

我有以下問題: Fortran90 +中的分配/釋放語句的實際開銷是多少? 即,幾個中型陣列在一個循環中分配的,像Fortran分配/取消分配

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

是否值得基於在這種情況下,最大尺寸分配一個單一的工作陣列?

+1

是否有顯着的節省取決於「富」運行需要多長時間。這個變化值得嗎?無論是觀點問題,還是應該在編譯器和機器上測量運行時間。更改是否使代碼不易讀?如果是這樣,這是值得保存毫秒的運行時間?秒? –

回答

6

我發現在緊密循環中動態數組分配可以真的減慢我的代碼的執行速度,valgrind顯示大部分循環被mallocfree佔用。所以如果foo是一個非常快速的函數,那麼值得靜態分配這個數組。通過使用valgrind的callgrind功能進行分析很容易發現這種開銷(可能值得減少問題的大小,因爲配置執行速度可能會降低至少10倍)。

在2008年的fortran中,這種類型的問題有更好的解決方案。您可以在運行時確定大小的block結構中聲明變量。這應該使編譯器在堆棧上分配變量要容易得多。但是我沒有親自使用過,我不確定哪些編譯器支持它。

+0

注意:gfortran [支持塊結構](http://fortranwiki.org/fortran/show/Fortran+2008+status) – max

3

使用ALLOCATEDEALLOCATE的開銷是相同的,如C.使用malloc()free()的開銷實際上最Fortran編譯器實現(DE)ALLOCATE圍繞malloc()/free()包裝增加了一些簿記,固有的所有的Fortran 90個陣列。

通常最好預先分配一個足夠大的scratch數組,並在緊密循環中使用它,而不是不斷分配和釋放內存。它還能避免碎片堆積,這可能會導致後期的分配問題(非常罕見的情況,但它發生,特別是對於32位代碼)。

+0

爲什麼使用32位代碼? – Rook

+2

由於32位代碼只能訪問堆,堆棧和內存映射文件之間共享的2 GiB用戶虛擬地址空間(或OS X上的4 GiB),並且堆的碎片很少,因此可能沒有足夠大的連續空間提供大塊的進一步分配。 –