Fortran: ¿La mejor manera de cronometrar secciones de su código?

15

A veces, mientras se optimiza el código, es necesario cronometrar ciertas partes del código, he estado usando lo siguiente durante años, pero me preguntaba si hay una manera más simple / mejor de hacerlo.

call system_clock(count_rate=clock_rate) !Find the time rate
call system_clock(count=clock_start)     !Start Timer

call do_something_subroutine             !This is what gets timed

call system_clock(count=clock_stop)      ! Stop Timer

e_time = real(clock_stop-clock_start)/real(clock_rate)
Oscilación Isopícnica
fuente

Respuestas:

11

Hay algunas otras formas de hacerlo, con ventajas e inconvenientes:

  • MPI_WTIME : este es un reloj de pared de alta resolución. Es probablemente la opción más 'confiable'; Simplemente funciona. La desventaja es que si su programa aún no usa MPI, tendrá que envolverlo (lo cual no es difícil).
  • Use un fortran intrínseco (como lo ha hecho): este es probablemente el más fácil y generalmente suficiente, pero podría no funcionar tan bien en una arquitectura extraña o para trabajos paralelos. Hay un poco de discusión sobre este desbordamiento de pila
  • Ajustar una llamada C: Fortran y C son compatibles con objetos, por lo que es bastante fácil escribir un contenedor alrededor de las llamadas C. Un código con el que trabajo utiliza getrusage, que podría ser una elección extraña. Hay muchas discusiones sobre esto en Stack Overflow.

Mi recomendación personal sería MPI_WTIME, ya que sabe que funcionará bien donde haya MPI. Aquí hay un ejemplo de una búsqueda rápida:

  include 'mpif.h'
  DOUBLE PRECISION :: start, end
  start = MPI_Wtime()

  ! code to be timed

  end   = MPI_Wtime()
  write(*,*) 'That took ',end-start,' seconds'
Max Hutchinson
fuente
4

Si usa el compilador GNU, consulte gprof .

En resumen, agregará el indicador -g a su compilador, así:

g77 -g -pg -0 myprogram myprogram.F

Luego, ejecute el resultado y aparecerá un archivo llamado gmon.out en su directorio. Luego llame

gprof --line myprogram gmon.out

Esto le dará un perfil de tiempo de CPU línea por línea.

icurays1
fuente
Gracias por la respuesta, solo tengo que aclarar que estaba pidiendo una solución programática. Un perfilador es genial, pero es más de lo que estaba pidiendo.
isopicna Oscilación
3
la bandera es -pg, -ges para símbolos de depuración (también interesante, pero no obligatorio)
RSFalcon7
He escuchado en varios lugares que los tiempos dados por gprof no son necesariamente precisos, como yosefk.com/blog/… , stackoverflow.com/questions/1777556/alternatives-to-gprof/… (y varias otras respuestas de Mike Dunlavey en desbordamiento de pila). Las herramientas como gprof y kcachegrind siguen siendo útiles, ya que el número de llamadas a funciones sigue siendo correcto y le dan algunos datos de tiempo, pero no lo trataría como un evangelio. El DOE tiene algunas herramientas para esto, pero no sé si son mejores que insertar temporizadores.
Geoff Oxberry
1
En serio, @IsopycnalOscillation intenta usar el generador de perfiles. Es algo nuevo que aprender, pero te ayudará enormemente (¡y limpiará tu código!) A la larga.
tmarthal
gracias @tmarthal He usado perfiladores antes y definitivamente usaré uno para mi próximo proyecto, estoy totalmente de acuerdo con lo que dijiste.
Oscilación isopícnica
2

Según lo mencionado por icurays1, la mejor elaboración de perfiles es. También puede simplificar ligeramente lo anterior ...

use utils
...
call tic()
   ! Section to be timed
call toc()
...
call tic()
   ! Section to be timed
call toc()
...

donde el módulo utils contiene ...

real(8) :: t1,t2
...
subroutine tic()
  implicit none
  call cpu_time(t1)
end subroutine tic

subroutine toc()
  implicit none
  call cpu_time(t2)
  ! if (rank==0) print*,"Time Taken -->", real(t2-t1)
  print*,"Time Taken -->", real(t2-t1)
end subroutine toc

Si tiene muchas de estas secciones, pase una cadena, por ejemplo, "section_id" en toc para que imprima la identificación / nombre junto con el tiempo.

stali
fuente
Sugeriría no hacer t1y t2global, sino pasar t1como parámetro a ambas funciones, para permitir múltiples temporizadores. También puede devolver el tiempo, no imprimir nada.
Pedro