私たちのFortranコードの1つをプロファイリングすると、計算時間の大部分(22.1%と17.2%)を占める2つのサブルーチンがあります。各ルーチンでは、時間の約5%がメモリの割り当てと解放に費やされます。これらのルーチンは次のようになります
MODULE foo
CONTAINS
SUBROUTINE bar( ... )
...
IMPLICIT NONE
...
REAL, ALLOCATABLE, DIMENSION(:,:) :: work
...
ALLOCATE (work(size1,size2))
...
DEALLOCATE (work)
END SUBROUTINE bar
...
END MODULE foo
これらのサブルーチンは、私のベンチマークで約4000〜5000回呼び出されるので、ALLOCATEとDEALLOCATEを削除したいと思います。これらを自動配列に変更すると、プロファイラー出力がに変更されます。
MODULE foo
CONTAINS
SUBROUTINE bar( ... )
...
IMPLICIT NONE
...
REAL, DIMENSION(size1,size2) :: work
...
END SUBROUTINE bar
...
END MODULE foo
結果のプロファイルをに変更します
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
gfortranがこれらをスタックに割り当てており、ヒープではないように見えますが、これらの配列が大きくなりすぎたときにいつ発生するかが心配です。
私が取っている2番目のアプローチは、これらの配列を1回割り当ておよび割り当て解除することです。
work_array.f
MODULE work_array
IMPLICIT NONE
REAL(rprec), ALLOCATABLE, DIMENSION(:,:) :: work
END MODULE work_array
これらをコードの別の部分に一度割り当てます。今、私のサブルーチンは次のようになります
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と無料はどこから来ていますか?これらのアレイを一度割り当てるようにこれを設定するにはどうすればよいですか?