resueltos programas programación problemas multiplicacion matriz matrices estandar ejemplos dinamica desviacion codigos arreglos fortran

programas - problemas resueltos de programación en fortran 95 pdf



Fortran: matrices dinámicas frente a matriz automática Evitar la asignación de memoria (2)

Como la matriz de work solo se usa dentro de la subrutina de bar , puede agregarle el atributo de save y asignarla cuando se invoque la subrutina 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 ya no se necesita la subrutina. 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 desasignar la matriz de work , si el uso de memoria es un problema.

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 como

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 son llamadas del orden de 4000-5000 veces en mi punto de referencia, por lo que me gustaría deshacerme de ALLOCATE 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

Parece que Gfortran los está asignando a la pila y no a ese montón, pero me preocupa cuándo ocurre 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 parece

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 mallocs extra y libres? ¿Cómo puedo configurar esto para que yo asigne estas matrices una vez?


Si puede salir adelante 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 asignación única 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.

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