Fortranのコードの1つをプロファイリングすると、計算時間の大部分(22.1%と17.2%)を占めるサブルーチンが2つあります。各ルーチンでは、時間の約5%がメモリの割り当てと解放に費やされます。これらのルーチンはFortran:動的配列vs.自動配列メモリ割り当ての回避
MODULE foo
CONTAINS
SUBROUTINE bar(...)
...
IMPLICIT NONE
...
REAL, ALLOCATABLE, DIMENSION(:,:) :: work
...
ALLOCATE (work(size1,size2))
...
DEALLOCATE (work)
END SUBROUTINE bar
...
END MODULE foo
のように見える私はALLOCATEとDEALLOCATEを取り除くしたいと思いますので、これらのサブルーチンは、私のベンチマークで〜4000〜5000倍程度に呼び出されます。これらを自動配列に変更すると、にプロファイラ出力が変更されます。
MODULE foo
CONTAINS
SUBROUTINE bar(...)
...
IMPLICIT NONE
...
REAL, DIMENSION(size1,size2) :: work
...
END SUBROUTINE bar
...
END MODULE foo
はのgfortranがスタックしていないこと、ヒープ上でこれらを割り当てているが、私はこれらの配列が大きくなりすぎたときに発生したときに心配ですように私には見えます
Running Time Symbol Name
20955.0ms 17.0% __totzsp_mod_MOD_totzsps
7.0ms 0.0% malloc
5.0ms 0.0% free
2.0ms 0.0% user_trap
16192.0ms 13.2% __tomnsp_mod_MOD_tomnsps
20.0ms 0.0% free
3.0ms 0.0% malloc
1.0ms 0.0% szone_size_try_large
への結果のプロファイルを変更します。
私が取っている2番目のアプローチは、これらの配列を一度割り当て、割り当てを解除することです。
work_array.f
MODULE work_array
IMPLICIT NONE
REAL(rprec), ALLOCATABLE, DIMENSION(:,:) :: work
END MODULE work_array
Iは、コードの異なる部分に一度これらを割り当てます。さて、私のサブルーチンは次のように見えます
MODULE foo
CONTAINS
SUBROUTINE bar(...)
...
USE work_array
IMPLICIT NONE
...
END SUBROUTINE bar
...
END MODULE foo
しかし、コードを実行すると、プロファイルが悪化します。
Running Time Symbol Name
30584.0ms 21.6% __totzsp_mod_MOD_totzsps
3494.0ms 2.4% free
3143.0ms 2.2% malloc
27.0ms 0.0% DYLD-STUB$$malloc_zone_malloc
19.0ms 0.0% szone_free_definite_size
6.0ms 0.0% malloc_zone_malloc
24325.0ms 17.1% __tomnsp_mod_MOD_tomnsps
2937.0ms 2.0% free
2456.0ms 1.7% malloc
23.0ms 0.0% DYLD-STUB$$malloc_zone_malloc
3.0ms 0.0% szone_free_definite_size
これらの余分なmallocはどこから来ていますか?これを設定してこれらの配列を一度割り当てることができますか?
Fortranのヒープ配列は、暗黙の 'malloc' /' free'呼び出しによって、各関数呼び出しで割り当てられ、割り当て解除されます。これらは、この点では 'ALLOCATABLE'配列と変わりません。 –
私はこれがifortで起こるとは思わないでしょう。私はあなたの2番目のアプローチを常に使用しています。つまり、割り当てを解除して再割り当てせずに何度も使用する事前割り当てバッファを持っています。 – bdforbes
あらかじめプロファイルを割り当てておくと、プロファイルが悪化する可能性はありません。理由を把握しましたか? – Lupocci