2012-07-04 2 views
7

次の質問があります。 Fortran90 +でのallocate/deallocate文の実際のオーバーヘッドは何ですか? すなわち、いくつかの中型アレイはFortran allocate/deallocate

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

ように、ループ内で割り当てられているが、この場合には、最大サイズに基づいて、単一の作業配列を割り当てることは価値がありますか?

+1

顕著な節約があるかどうかは、「foo」を実行するのにかかる時間によって異なります。変化は価値があるのですか?意見の問題か、コンパイラとマシンの実行時間を測定する必要があります。変更によってコードが読みにくくなりますか?もしそうなら、それは実行時間のミリ秒を節約する価値がありますか?秒ですか? –

答えて

6

私はタイトなループ内の動的配列割り振りがコードの実行を実際に遅くすることがあることを発見しました。これは、valgrindが大きいサイクルの割合がmallocfreeであることを示しています。したがって、fooが非常に高速な関数であれば、この配列を静的に割り当てる価値があります。 valgrindのcallgrind機能を使用してプロファイリングすることでこのオーバーヘッドを簡単に見ることができます(プロファイリングされた実行が少なくとも10倍遅くなる可能性があるため、問題のサイズを小さくする価値があります)。

fortran 2008には、この種の問題にはより良い解決策があります。実行時に決定されたサイズのblockコンストラクト内で変数を宣言できます。これは、コンパイラが変数をスタックに割り当てることをはるかに簡単にするはずです。しかし私はこれを個人的に使用しておらず、どのコンパイラがそれをサポートしているのかよくわかりません。

+0

注:gfortran [ブロック構造をサポート](http://fortranwiki.org/fortran/show/Fortran+2008+status) – max

3

ALLOCATEDEALLOCATEを使用するオーバーヘッドは、実際にはほとんどのFortranコンパイラは、すべてのFortran 90の配列に固有のいくつかの追加簿記とmalloc()/free()のラッパーとして(DE)ALLOCATEを実装C.におけるmalloc()free()を使用するオーバーヘッドと同じです。

通常、十分な大きさのスクラッチアレイを事前に割り当てて、メモリを常に割り当てたり解放したりするのではなく、タイトなループで使用する方がよいでしょう。ヒープの断片化を防ぎ、後で割り当て問題につなげることもあります(非常にまれな状況ですが、特に32ビットコードで発生します)。

+0

なぜ32ビットコードですか? – Rook

+2

32ビットコードは、ヒープ、スタック、およびメモリマップされたファイル間で共有されるユーザー仮想アドレス空間の2 GiB(またはOS X上の4 GiB)にしかアクセスできないため、ひどく断片化されたヒープでは、大きなチャンクをさらに割り当てます。 –