web-dev-qa-db-ja.com

Fortran組み込みタイミングルーチン、どちらが良いですか? cpu_timeまたはsystem_clock

FORTRANプログラムのタイミングをとるとき、私は通常、コマンドcall cpu_time(t)を使用します。
そして、同じことをしているように見えるcall system_clock([count,count_rate,count_max])を偶然見つけました。しかし、より難しい邸宅で。これらについての私の知識は以下から得られます: 古いIntelのドキュメント
インテルのホームページでそれを見つけることができませんでした。以下のマークアップを参照してください。

  1. どちらがより正確ですか、それとも似ていますか?
  2. それらの1つはキャッシュミス(またはその他の種類)をカウントし、もう1つはカウントしませんか?
  3. または、以下のマークアップでマークされたものだけが違いますか?

これらは私の質問です。以下に、タイミングと使用法を確認するためのコードを示します。彼らは私にそれらが出力で非常に似ていることを示し、したがって実装でも似ているように見えます。
私はおそらく常にcpu_time、そして私は本当により正確なタイミングを必要としません。

以下のコードで、それらを比較しようとしました。 (私はより手の込んだことも試みましたが、簡潔さを保つために供給しません)だから基本的に私の結果は次のとおりです:

  • cpu_time
    1. 使いやすく、初期化呼び出しは必要ありません
    2. 違いの直接時間
    3. また、コンパイラ固有である必要がありますが、精度を確認する方法はありません。 (標準はミリ秒です)
    4. はスレッド時間の合計です。つまり並列実行にはお勧めしません。
  • system_clock
    1. 初期化が必要です。
    2. 後処理、分割の形で。 (小さなことですが、それでも違いがあります)
    3. コンパイラ固有です。私のPCで次が見つかりました:
      • Intel 12.0.4は、INTEGERの精度により、カウントレート10000を使用します。
      • gcc-4.4.5は1000を使用しますが、これがどのように区別されるかわかりません
    4. wraparoundsに遭遇する傾向がある、つまりc1 > c2、 のため count_max
    5. 1つの標準時間からの時間です。したがって、これは合計ではなく、1つのスレッドの実際の時間になります

コード:

PROGRAM timer
  IMPLICIT NONE
  REAL :: t1,t2,rate 
  INTEGER :: c1,c2,cr,cm,i,j,n,s
  INTEGER , PARAMETER :: x=20000,y=15000,runs=1000
  REAL :: array(x,y),a_diff,diff

  ! First initialize the system_clock
  CALL system_clock(count_rate=cr)
  CALL system_clock(count_max=cm)
  rate = REAL(cr)
  WRITE(*,*) "system_clock rate ",rate

  diff = 0.0
  a_diff = 0.0
  s = 0
  DO n = 1 , runs
     CALL CPU_TIME(t1)
     CALL SYSTEM_CLOCK(c1)
     FORALL(i = 1:x,j = 1:y)
        array(i,j) = REAL(i)*REAL(j) + 2
     END FORALL
     CALL CPU_TIME(t2)
     CALL SYSTEM_CLOCK(c2)
     array(1,1) = array(1,2)     
     IF ( (c2 - c1)/rate < (t2-t1) ) s = s + 1
     diff = (c2 - c1)/rate - (t2-t1) + diff
     a_diff = ABS((c2 - c1)/rate - (t2-t1)) + a_diff
  END DO

  WRITE(*,*) "system_clock : ",(c2 - c1)/rate
  WRITE(*,*) "cpu_time     : ",(t2-t1)
  WRITE(*,*) "sc < ct      : ",s,"of",runs
  WRITE(*,*) "mean diff    : ",diff/runs
  WRITE(*,*) "abs mean diff: ",a_diff/runs
END PROGRAM timer

ここでiを完了するには、Intel 12.0.4およびgcc-4.4.5コンパイラからの出力を提供します。

  • Intel 12.0.4-O0

    system_clock rate    10000.00    
    system_clock :    2.389600    
    cpu_time     :    2.384033    
    sc < ct      :            1 of        1000
    mean diff    :   4.2409324E-03
    abs mean diff:   4.2409897E-03
    
    real    42m5.340s
    user    41m48.869s
    sys 0m12.233s
    
  • gcc-4.4.5-O0

    system_clock rate    1000.0000    
    system_clock :    1.1849999    
    cpu_time     :    1.1840820    
    sc < ct      :          275 of        1000  
    mean diff    :   2.05709646E-03  
    abs mean diff:   2.71424348E-03  
    
    real    19m45.351s  
    user    19m42.954s  
    sys 0m0.348s  
    

読んでくれてありがとう...

26
zeroth

これら2つの組み込み関数は、異なるタイプの時間を報告します。 system_clockは「ウォールタイム」または経過時間を報告します。 cpu_timeは、CPUが使用した時間を報告します。マルチタスクマシンでは、これらは非常に異なる可能性があります。たとえば、プロセスが他の3つのプロセスとCPUを同等に共有し、CPUの25%を受け取り、10 cpu秒を使用した場合、実際の経過時間または壁には約40秒かかります。時刻。

18
M. S. B.

cpu_time()は通常、Intel互換CPUでは約0.01秒の解像度です。これは、短い時間間隔はゼロ時間としてカウントされる可能性があることを意味します。 Linuxの最新のコンパイラーは、system_clock()の解像度を引数のデータ型に依存させるため、integer(int64)は1マイクロ秒よりも優れた解像度を提供し、かなりの時間間隔でカウントできるようにします。 Windows用のgfortranは、system_clock()がquery_performance呼び出しと同等になるように最近(2015年中に)変更されました。ただし、ifort Windowsでは、omp_get_wtimeがquery_performanceを使用するように変更された後でも、system_clockの解像度は約0.01のままです。特に、CPUまたはデータバスのティックに関連すると考えられる場合、rdtsc命令などが報告する可能性がある場合は、クロックティックでのcpu_timeまたはsystem_clockの解像度の測定に関する以前のコメントを無視します。

5
tim18

itimegfortranマニュアル を参照)がsystem_clock fortranプログラムのタイミング。使い方はとても簡単です。

integer, dimension(3) :: time
call itime(time)
print *, 'Hour:  ', time(1)
print *, 'Minute:', time(2)
print *, 'Second:', time(3)
3

Seconds()が実時間を取得する最も簡単な方法であることがわかりました。その使用法はcpu_time()とほとんど同じです。

real(8)::t1,delta
t1=secnds(0.0)
!Do stuff
delta=seconds(t1)
0
bdforbes