Fortran:コードのセクションの時間を計る最良の方法は?


15

コードの最適化中にコードの特定の部分の時間を測定することが必要になる場合がありますが、私は長年にわたって次のものを使用していましたが、それを行うより簡単/より良い方法があるかどうか疑問に思っていましたか?

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)

回答:


11

これを行うには他にもいくつかの方法があり、利点と欠点があります。

  • MPI_WTIME:これは高解像度の壁時計です。これはおそらく最も信頼できるオプションです。それだけで動作します。欠点は、プログラムがまだMPIを使用していない場合、MPIをラップする必要があることです(これは難しくありません)。
  • fortran組み込み関数を(使用しているとおりに)使用する:これはおそらく最も簡単で一般的には十分ですが、奇妙なアーキテクチャや並列ジョブではうまく動作しない可能性があります。このスタックオーバーフローについては、少し議論があります。
  • C呼び出しをラップする:FortranとCはオブジェクト互換であるため、C呼び出しのラッパーを書くのは簡単です。私が使用しているコードはgetrusageを使用していますが、これは奇妙な選択かもしれません。これについては、Stack Overflowで多くの 議論があります。

私が個人的に推奨するのはMPI_WTIMEです。MPIがあればどこでもうまく機能することがわかっています。ここでクイック検索から:

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

  ! code to be timed

  end   = MPI_Wtime()
  write(*,*) 'That took ',end-start,' seconds'

4

GNUコンパイラを使用する場合は、gprofを確認してください。

つまり、次のようにコンパイラに-gフラグを追加します。

g77 -g -pg -0 myprogram myprogram.F

次に、出力を実行すると、gmon.outというファイルがディレクトリに表示されます。その後、呼び出します

gprof --line myprogram gmon.out

これにより、行ごとのCPU時間プロファイルが得られます。


答えてくれてありがとう、私はプログラムによる解決策を求めていることを明確にしなければなりません。プロファイラーは素晴らしいですが、それは私が求めていた以上のものです。
密度振動

3
フラグは-pg-gデバッグシンボル用です(興味深いが、必須ではありません)
-RSFalcon7

私のような、gprofのによって与えられたタイミングは必ずしも正確ではないことを複数の場所で聞いたyosefk.com/blog/...stackoverflow.com/questions/1777556/alternatives-to-gprof/...(および他のさまざまなマイクDunlavey回答スタックオーバーフロー)。gprofやkcachegrindなどのツールは、関数呼び出しの数が依然として正しいという点で依然として有用であり、タイミングデータを提供しますが、私はそれを福音として扱いません。DOEにはこのためのツールがいくつかありますが、タイマーを挿入するよりも優れているかどうかはわかりません。
ジェフオックスベリー

1
真剣に、@ IsopycnalOscillationはプロファイラーを使用しようとします。学ぶことは新しいことですが、長い目で見れば非常に役立ちます(そしてコードをクリーンアップします!)。
-tmarthal

ありがとう@tmarthal以前にプロファイラーを使用しましたが、次のプロジェクトでプロファイラーを使用することは間違いありません-あなたが言ったことに完全に同意します。
密度振動

2

icurays1で述べたように、プロファイリングが最適です。上記を少し単純化することもできます...

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

utilsモジュールには...

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

そのようなセクションが多数ある場合は、tocの「section_id」などの文字列を渡して、タイミングとともにid / nameを出力します。


私は作っていないことをお勧めt1し、t2グローバルではなく渡すt1複数のタイマーを可能にするために、両方の機能をパラメータとして。また、何も印刷せずに、単に時間を返すこともできます。
ペドロ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.