Fortran: melhor maneira de cronometrar seções do seu código?

15

Às vezes, ao otimizar o código, é necessário cronometrar determinadas partes do código, eu venho usando o seguinte há anos, mas fiquei imaginando se existe uma maneira melhor / mais simples de fazer isso?

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)
Oscilação isópcica
fonte

Respostas:

11

Existem algumas outras maneiras de fazer isso, com vantagens e desvantagens:

  • MPI_WTIME : Este é um relógio de parede de alta resolução. É provavelmente a opção mais `confiável '; simplesmente funciona. A desvantagem é que, se o seu programa ainda não usa MPI, você terá que envolvê-lo (o que não é difícil).
  • Use um fortran intrínseco (como você tem): provavelmente é o mais fácil e geralmente suficiente, mas pode não funcionar tão bem em uma arquitetura estranha ou em trabalhos paralelos. Há um pouco de discussão sobre esse estouro de pilha
  • Finalizar uma chamada em C: Fortran e C são compatíveis com objetos, portanto é fácil escrever um wrapper em torno de chamadas em C. Um código com o qual trabalho usa getrusage, que pode ser uma escolha estranha. Há muitas discussões sobre isso no Stack Overflow.

Minha recomendação pessoal seria MPI_WTIME, como você sabe, funcionará bem onde houver MPI. Aqui está um exemplo de uma pesquisa 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
fonte
4

Se você usa o compilador GNU, consulte o gprof .

Em resumo, você adicionará o sinalizador -g ao seu compilador, assim:

g77 -g -pg -0 myprogram myprogram.F

Em seguida, execute a saída e um arquivo chamado gmon.out aparecerá no seu diretório. Em seguida, ligue

gprof --line myprogram gmon.out

Isso fornecerá um perfil de tempo de CPU linha por linha.

icurays1
fonte
Obrigado pela resposta, só preciso esclarecer que estava pedindo uma solução programática. Um criador de perfil é ótimo, mas é mais do que eu estava pedindo.
Oscilação isópica
3
a bandeira é -pg, -gé para símbolos de depuração (também interessante, mas não é obrigatório)
RSFalcon7
Ouvi em vários lugares que os horários fornecidos pelo gprof não são necessariamente precisos, como yosefk.com/blog/… , stackoverflow.com/questions/1777556/alternatives-to-gprof/… (e várias outras respostas de Mike Dunlavey estouro de pilha). Ferramentas como gprof e kcachegrind ainda são úteis, pois o número de chamadas de função ainda está correto e fornecem alguns dados de tempo, mas eu não os trataria como evangelho. O DOE tem algumas ferramentas para isso, mas não sei se elas são melhores do que inserir temporizadores.
precisa saber é o seguinte
1
Sério, @IsopycnalOscillation tenta usar o criador de perfil. É algo novo para aprender, mas irá ajudá-lo tremendamente (e limpar seu código!) A longo prazo.
tmarthal
thanks @tmarthal Eu já usei profilers antes e definitivamente usarei um para o meu próximo projeto - concordo totalmente com o que você disse.
Oscilação isópcica
2

Conforme mencionado pelo icurays1, a criação de perfil é a melhor. Você também pode simplificar um pouco o acima ...

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

onde o módulo utils contém ...

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

Se você tiver muitas seções, passe uma string, por exemplo, "section_id" em toc para que ela imprima o ID / nome junto com o tempo.

stali
fonte
Eu sugeriria não fazer t1e t2global, mas passar t1como parâmetro para ambas as funções, para permitir vários temporizadores. Você também pode simplesmente retornar a hora, não imprimir nada.
Pedro