2012-06-26 13 views
8

Profilowanie jednego z naszych kodów fortranowych obejmuje dwa podprogramy, które zajmują większość czasu obliczeniowego (22,1% i 17,2%). W każdej z procedur około 5% czasu zajmuje przydzielanie i zwalnianie pamięci. Procedury te wyglądająFortran: dynamiczne tablice vs. automatyczna tablica Unikanie alokacji pamięci

MODULE foo 

CONTAINS 

SUBROUTINE bar(...) 
... 
IMPLICIT NONE 
... 
REAL, ALLOCATABLE, DIMENSION(:,:) :: work 
... 
ALLOCATE (work(size1,size2)) 
... 
DEALLOCATE (work) 
END SUBROUTINE bar 
... 
END MODULE foo 

te podprogramy sprawdzony rzędu ~ 4000-5000 razy w moim znakiem ławce więc chciałbym się pozbyć alokuje i zwalnianie. Zmiana tych na automatyczne tablice zmienia profil na wyjściowy profiler.

MODULE foo 

CONTAINS 

SUBROUTINE bar(...) 
... 
IMPLICIT NONE 
... 
REAL, DIMENSION(size1,size2) :: work 
... 
END SUBROUTINE bar 
... 
END MODULE foo 

Zmienia wynikowy profil do

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 

I wygląda gfortran przeznacza je na stosie, a nie, że sterty ale jestem zaniepokojony, kiedy się dzieje, gdy te tablice stają się zbyt duże.

Drugie podejście, które podejmuję, to przydzielenie i zwolnienie tych tablic jeden raz.

work_array.f

MODULE work_array 
IMPLICIT NONE 

REAL(rprec), ALLOCATABLE, DIMENSION(:,:) :: work 

END MODULE work_array 

mogę przeznaczyć je raz w innej części kodu. Teraz mój podprogram wygląda jak

MODULE foo 

CONTAINS 

SUBROUTINE bar(...) 
... 
USE work_array 
IMPLICIT NONE 
... 
END SUBROUTINE bar 
... 
END MODULE foo 

Jednak po uruchomieniu kodu profil staje się coraz gorszy.

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 

Skąd się biorą te dodatkowe mallokso i zwalnia? Jak mogę to ustawić, aby przydzielić te tablice jeden raz?

+1

Tablice sterty w Fortranie są przydzielane i zwalniane w każdym wywołaniu funkcji przez niejawne wywołania 'malloc' /' free'.Nie różnią się one od tablic "ALLOCATABLE" w tym zakresie. –

+1

Nie spodziewałbym się, że tak się stanie z programem ifort. Używam twojego drugiego podejścia przez cały czas, tj. Mając wstępnie przydzielony bufor, którego używam wielokrotnie, bez zwolnienia i ponownego przydzielenia. – bdforbes

+0

Nie jest możliwe, że profil pogorszy się po przydzieleniu jednego z góry ... Czy wiesz, dlaczego? – Lupocci

Odpowiedz

4

Ponieważ tablica work jest używany tylko wewnątrz bar podprogramu, można dodać atrybut save do niej i przeznaczyć go, gdy podprogram nazywa się po raz pierwszy. Jeśli work1 lub work2 jest inna niż w poprzednich połączeniach, możesz po prostu ponownie przydzielić tablicę w takim przypadku.

Pozostawia to problem dealokacji, gdy podprogram nie jest już potrzebny. Jeśli chcesz zadzwonić w ciągu całego cyklu życia programu, nie ma problemu, ponieważ system operacyjny powinien zwolnić pamięć po zakończeniu programu. Z drugiej strony, jeśli potrzebujesz go tylko podczas inicjalizacji, pamięć pozostanie przydzielona, ​​nawet jeśli nie jest potrzebna. Być może możesz dodać argument do podprogramu, który nakazuje mu zwolnić tablicę work, jeśli użycie pamięci jest problemem.

0

Jeśli można uzyskać przy pojedynczym przydziale przy inicjalizacji programu, nie ma powodu, aby tablica była definiowalna jako przydzielająca. Połóż to we wspólnym.

Jeśli potrzebujesz tylko ustalonego rozmiaru, ale nie znasz tego rozmiaru do czasu wykonania, musisz przejść do ostatniej opcji, jednej alokacji przy inicjalizacji. Jednak nie ma sensu, że zwiększyło to trafność alokacji. Musiałbym zobaczyć definicję i kod przydziału, aby powiedzieć więcej.

Ponieważ przydzielono pamięć wirtualną, "użycie pamięci" nie stanowi problemu, chyba że tablica jest tak duża, że ​​wpływa na dostępną przestrzeń adresową.

Powiązane problemy