2012-07-04 9 views
7

Tengo la siguiente pregunta: ¿Cuál es la sobrecarga real de las instrucciones allocate/deallocate en Fortran90 +? es decir, varias matrices de tamaño medio se asignan dentro de un bucle, comoFortran asignar/desasignar

do i = 1, 1000 
    allocate(tmp(20)) 
    tmp(1:20) = 1d0 
    call foo(tmp) 
    deallocate(tmp) 
end do 

¿Vale la pena asignar una única matriz trabajo basado en el tamaño máximo en este caso?

+1

Si hay ahorros notables depende de cuánto tiempo lleve "foo" para ejecutarse. ¿Vale la pena el cambio? Es una cuestión de opinión, o debería medir el tiempo de ejecución en su compilador y máquina. ¿El cambio hace que el código sea menos legible? Si es así, ¿vale la pena guardar milisegundos de tiempo de ejecución? ¿segundos? –

Respuesta

6

He encontrado que la asignación dinámica de matrices en bucles estrechos realmente puede ralentizar la ejecución de mi código, con valgrind que muestra que un gran porcentaje de ciclos se toma por malloc y free. Entonces, si foo es una función muy rápida, valdría la pena asignar esta matriz de forma estática. Es fácil ver esta sobrecarga mediante el uso de perfiles usando la funcionalidad callgrind valgrind (puede valer la pena reducir el tamaño de su problema ya que la ejecución perfilada puede ser al menos 10 veces más lenta).

En fortran 2008 hay una mejor solución para este tipo de problema. Puede declarar sus variables dentro de una construcción block con un tamaño determinado en tiempo de ejecución. Esto debería hacer que sea mucho más fácil para el compilador asignar la variable en la pila. Sin embargo, no lo he usado personalmente y no estoy seguro de qué compiladores lo admiten.

+0

Nota: gfortran [admite construcciones de bloques] (http://fortranwiki.org/fortran/show/Fortran+2008+status) – max

3

La sobrecarga de utilizar ALLOCATE y DEALLOCATE es la misma que la sobrecarga de la utilización de malloc() y free() en C. En realidad la mayoría de los compiladores de Fortran implementan (DE)ALLOCATE como envolturas alrededor malloc()/free() con un poco de contabilidad añadido, inherentes a los 90 arrays FORTRAN.

Por lo general, es mejor preasignar una matriz de arañazos suficientemente grande y utilizarla en bucles ajustados en lugar de asignar y liberar constantemente la memoria. También evita que el montón se fragmente, lo que podría ocasionar problemas de asignación más adelante (situación muy rara pero sucede, especialmente con códigos de 32 bits).

+0

¿Por qué con códigos de 32 bits? – Rook

+2

Debido a que los códigos de 32 bits tienen acceso a solo 2 GiB de espacio de direcciones virtuales de usuario (o 4 GiB en OS X) compartidos entre montón, pila y archivos mapeados en memoria y con un montón fragmentado incorrectamente, puede que no haya suficiente espacio continuo para proporcionar más asignaciones de grandes trozos. –