次の質問があります: 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
ますfree
。したがって、foo
が非常に高速な関数である場合は、この配列を静的に割り当てる価値があります。valgrindのcallgrind機能を使用してプロファイリングすることで、このオーバーヘッドを簡単に確認できます(プロファイリングされた実行は少なくとも10倍遅くなる可能性があるため、問題のサイズを減らす価値があるかもしれません)。
fortran 2008では、このタイプの問題に対するより良い解決策があります。block
実行時に決定されたサイズで、構成内で変数を宣言できます。これにより、コンパイラがスタックに変数を割り当てるのがはるかに簡単になります。しかし、私はこれを個人的に使用したことがなく、どのコンパイラがそれをサポートしているかわかりません。
ALLOCATE
およびを使用するオーバーヘッドは、CでのおよびDEALLOCATE
を使用するオーバーヘッドと同じです。実際、ほとんどのFortranコンパイラーは、すべてのFortran 90配列に固有の、いくつかの追加の簿記を備えたラッパーとして実装します。malloc()
free()
(DE)ALLOCATE
malloc()/free()
通常、メモリを絶えず割り当てて解放するのではなく、十分な大きさのスクラッチアレイを事前に割り当てて、タイトなループで使用することをお勧めします。また、ヒープが断片化されて、後で割り当ての問題が発生するのを防ぎます(非常にまれな状況ですが、特に32ビットコードで発生します)。