2012-06-26 18 views
8

Al perfilar uno de nuestros códigos fortran, hay dos subrutinas que ocupan la mayor parte del tiempo computacional (22.1% y 17.2%). En cada rutina, ~ 5% del tiempo se gasta en asignar y liberar memoria. Estas rutinas se ven comoFortran: matrices dinámicas frente a matriz automática Evitar la asignación de memoria

MODULE foo 

CONTAINS 

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

estas subrutinas llaman a ellas del orden de ~ 4000-5000 veces en mi punto de referencia por lo que me gustaría deshacerse de asignar y DEALLOCATE. Cambiar estos a arreglos automáticos cambia a la salida del generador de perfiles.

MODULE foo 

CONTAINS 

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

Cambia el perfil resultante a

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 

Me parece que gfortran es la asignación de éstos en la pila y no ese montón, pero me preocupa cuando sucede cuando estas matrices se vuelven demasiado grandes.

El segundo enfoque que estoy tomando es asignar y desasignar estas matrices una vez.

work_array.f

MODULE work_array 
IMPLICIT NONE 

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

END MODULE work_array 

asigno estos una vez en una parte diferente del código. Ahora mi subrutina se parece a

MODULE foo 

CONTAINS 

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

Sin embargo, cuando ejecuto el código ahora el perfil empeora.

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 

¿De dónde vienen estos extra mallocs y libres? ¿Cómo puedo configurar esto para que yo asigne estas matrices una vez?

+1

Las matrices de montón en Fortran se asignan y desasignan en cada llamada de función mediante llamadas 'malloc' /' free' implícitas.No son diferentes de las matrices 'ALLOCATABLE' a este respecto. –

+1

No esperaría que esto suceda con ifort. Uso su segundo enfoque todo el tiempo, es decir, tener un búfer preasignado que utilizo muchas veces sin desasignar ni reasignar. – bdforbes

+0

No es posible que el perfil empeore cuando asigna uno de antemano ... ¿descubrió por qué? – Lupocci

Respuesta

4

Desde la matriz work sólo se utiliza dentro de la bar subrutina, se podría añadir el atributo save a él y asignarlo cuando la subrutina se llama por primera vez. Si work1 o work2 es diferente en comparación con llamadas anteriores, puede reasignar la matriz en ese caso.

Esto deja el problema de la desasignación una vez que la subrutina ya no es necesaria. Si necesita llamar durante toda la vida útil del programa, no hay problema, ya que el sistema operativo debe desasignar la memoria cuando se cierra el programa. Por otro lado, si solo lo necesita durante la inicialización, la memoria permanecerá asignada incluso cuando no sea necesaria. Tal vez pueda agregar un argumento a la subrutina que le indique que desasigne la matriz work, si el uso de memoria es un problema.

0

Si puede pasar con una única asignación en la inicialización del programa, entonces no hay ninguna razón para que la matriz se defina como asignable. Ponlo en común.

Si solo necesita un tamaño fijo, pero no conoce ese tamaño hasta el tiempo de ejecución, necesitará ir con su opción final, una única asignación en la inicialización. Sin embargo, no tiene sentido que esto haya incrementado el impacto en el rendimiento de la asignación. Necesitaría ver la definición y el código de asignación para decir más.

Dado que lo que se asigna es memoria virtual, el "uso de memoria" no es realmente un problema, a menos que la matriz sea tan grande que afecte el espacio de direcciones disponible.

Cuestiones relacionadas