При профилировании одного из наших кодов на Фортране есть две подпрограммы, которые занимают большую часть вычислительного времени (22,1% и 17,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 размещает их в стеке, а не в этой куче, но меня беспокоит, когда эти массивы становятся слишком большими.
Второй подход, который я использую, состоит в том, чтобы выделить и освободить эти массивы один раз.
работа _массив.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 и free? Как я могу настроить это так, чтобы я выделял эти массивы один раз?