Fortran: Cara terbaik untuk menentukan waktu bagian kode Anda?

15

Terkadang saat mengoptimalkan kode diperlukan untuk menentukan waktu bagian tertentu dari kode, saya telah menggunakan yang berikut selama bertahun-tahun tetapi bertanya-tanya apakah ada cara yang lebih sederhana / lebih baik untuk melakukannya?

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)
Osilasi Isopycnal
sumber

Jawaban:

11

Ada beberapa cara lain untuk melakukan ini, dengan kelebihan dan kekurangan:

  • MPI_WTIME : Ini adalah jam dinding resolusi tinggi. Ini mungkin opsi yang paling 'dipercaya'; itu hanya berfungsi. Kelemahannya adalah jika program Anda belum menggunakan MPI, Anda harus membungkus MPI di sekitarnya (yang tidak sulit).
  • Gunakan fortran intrinsik (seperti yang Anda miliki): Ini mungkin yang termudah, dan umumnya cukup, tetapi mungkin tidak bekerja dengan baik pada arsitektur yang aneh atau untuk pekerjaan paralel. Ada sedikit diskusi tentang Stack Overflow ini
  • Membungkus panggilan C: Fortran dan C kompatibel dengan objek, sehingga cukup mudah untuk menulis pembungkus panggilan C. Kode yang saya gunakan menggunakan getrusage, yang mungkin merupakan pilihan aneh. Ada banyak diskusi tentang ini di Stack Overflow.

Rekomendasi pribadi saya adalah MPI_WTIME, karena Anda tahu itu akan berfungsi dengan baik di mana pun ada MPI. Ini adalah contoh dari pencarian cepat:

  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
sumber
4

Jika Anda menggunakan kompiler GNU, periksa gprof .

Singkatnya, Anda akan menambahkan flag -g ke kompiler Anda, seperti:

g77 -g -pg -0 myprogram myprogram.F

Kemudian, jalankan output, dan file bernama gmon.out akan muncul di direktori Anda. Lalu, teleponlah

gprof --line myprogram gmon.out

Ini akan memberikan profil waktu CPU baris demi baris.

icurays1
sumber
Terima kasih atas jawabannya, saya hanya perlu mengklarifikasi bahwa saya meminta solusi terprogram. Seorang profiler hebat tetapi itu lebih dari apa yang saya minta.
Osilasi Isopycnal
3
bendera adalah -pg, -guntuk simbol debug (juga menarik, tetapi tidak diperlukan)
RSFalcon7
Saya telah mendengar di banyak tempat bahwa pengaturan waktu yang diberikan oleh gprof belum tentu akurat, seperti yosefk.com/blog/… , stackoverflow.com/questions/1777556/alternatives-to-gprof/… (dan berbagai jawaban Mike Dunlavey lainnya) pada Stack Overflow). Alat-alat seperti gprof dan kcachegrind masih berguna, karena jumlah pemanggilan fungsi masih benar, dan mereka memberi Anda beberapa data waktu, tetapi saya tidak akan memperlakukannya sebagai Injil. DOE memiliki beberapa alat untuk ini, tapi saya tidak tahu apakah mereka lebih baik daripada memasukkan timer.
Geoff Oxberry
1
Serius, @IsopycnalOscillation mencoba menggunakan profiler. Ini adalah sesuatu yang baru untuk dipelajari, tetapi itu akan sangat membantu Anda (dan membersihkan kode Anda!) Dalam jangka panjang.
tmarthal
terima kasih @tmarthal Saya telah menggunakan profiler sebelumnya dan saya pasti akan menggunakan satu untuk proyek berikutnya - saya sangat setuju dengan apa yang Anda katakan.
Osilasi Isopycnal
2

Seperti disebutkan oleh profil icurays1 adalah yang terbaik. Anda juga dapat sedikit menyederhanakan hal di atas ...

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

di mana modul utils berisi ...

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

Jika Anda memiliki banyak bagian seperti itu maka berikan string, misalnya, "section_id" di toc sehingga ia mencetak id / nama bersama dengan waktu.

stali
sumber
Saya akan menyarankan tidak membuat t1dan t2global, melainkan lewat t1sebagai parameter untuk kedua fungsi, untuk memungkinkan beberapa timer. Anda juga bisa mengembalikan waktu, bukan mencetak apa pun.
Pedro