2013-02-22 10 views
8

私は正確なタイミングが重要で、C++ 11で指定された3種類のクロック、すなわちsystem_clock,steady_clock、およびhigh_resolution_clockを調べていました。 私の最初の懸念は、さまざまなタイプのクロックに対するコールオーバーヘッドに違いがあるかどうかをテストし、各タイプのクロックの解像度をチェックすることでした。私はG ++ 4.7.2でコンパイルさC++ 11クロック:g ++ steady_clock :: is_steady == false?

$ g++-4.7 -std=c++11 -Dhrc chrono.cpp -o hrc_chrono 
chrono.cpp:15:2: warning: #warning "High resolution clock" [-Wcpp] 
$ g++-4.7 -std=c++11 -Dsys chrono.cpp -o sys_chrono 
chrono.cpp:15:2: warning: #warning "System clock" [-Wcpp] 
$ g++-4.7 -std=c++11 -Dsc chrono.cpp -o sc_chrono 
chrono.cpp:15:2: warning: #warning "Steady clock" [-Wcpp] 

Iでそれをコンパイルし、

  • SUSE Linuxでは、カーネルv3.1.10でそれを実行した

    #include <chrono> 
    #include <cstdio> 
    using namespace std; 
    using namespace std::chrono; 
    
    int main(int argc, char **argv) 
    { 
        size_t N = 1e6; 
        if(2 == argc) { 
        sscanf(argv[1], "%zu", &N); 
        } 
    
    #if defined(hrc) 
        typedef high_resolution_clock clock; 
    #warning "High resolution clock" 
    #elif defined(sc) 
        typedef steady_clock clock; 
    #warning "Steady clock" 
    #elif defined(sys) 
        typedef system_clock clock; 
    #warning "System clock" 
    #endif 
    
        const double resolution = double(clock::period::num)/double(clock::period::den); 
    
        printf("clock::period: %lf us.\n", resolution*1e6); 
        printf("clock::is_steady: %s\n", clock::is_steady ? "yes" : "no"); 
        printf("Calling clock::now() %zu times...\n", N); 
    
        // first, warm up 
        for(size_t i=0; i<100; ++i) { 
        time_point<clock> t = clock::now(); 
        } 
    
        // loop N times 
        time_point<clock> start = clock::now(); 
        for(size_t i=0; i<N; ++i) { 
        time_point<clock> t = clock::now(); 
        } 
        time_point<clock> end = clock::now(); 
    
        // display duration 
        duration<double> time_span = duration_cast<duration<double>>(end-start); 
        const double sec = time_span.count(); 
        const double ns_it = sec*1e9/N; 
        printf("That took %lf seconds. That's %lf ns/iteration.\n", sec, ns_it); 
    
        return 0; 
    } 
    

    : は、ここに私のサンプルプログラムです、CPU i7

  • Angstrom Linux組み込みシステム、カーネルv3.1.10、MCU Tegra 2(ARM Cortex A9)。

最初の驚くべきことは、3種類のクロックが明らかに同義語であることでした。それらはすべて同じ周期(1マイクロ秒)を持ち、時間/呼び出しは実質的に同じです。 3種類のクロックを同じにするとどういう意味ですか?chronoのG ++実装はまだ成熟していないからですか?あるいは、3.1.10カーネルにはユーザーアクセス可能なクロックが1つしかないかもしれませんか?

2番目の驚きは、これは巨大です、それはsteady_clock :: is_steady == falseです。私は、定義上、そのプロパティが真でなければならないことをかなり確信しています。何を与える?どのように私はそれを回避することができます(つまり、安定したクロックを達成する)?

他のプラットフォーム/コンパイラで簡単なプログラムを実行できるのであれば、結果を知りたいと思うでしょう。誰もが疑問に思っているならば、それは私のCore i7の上の約25ナノ秒/反復だ、1000のNS /イテレーションのTegra 2.

+0

の3つのクロックタイプすべてについてのコメント)私は '-DXXX'フラグで指定されている時計の種類ごとにコードを3回コンパイルしています。 'g ++'の最後の引数は、実行可能ファイルのファイル名だけです。これは、リックには関係ありません。 (私はそれがどの種類の時計とプログラムがクロノライブラリを使っているのかを反映しています) –

+0

申し訳ありませんが、私は完全にコマンドラインを誤読しました –

答えて

8

steady_clock4ドキュメントによって示されるようには(GCC 4.7でサポートされています。7リリース:http://gcc.gnu.org/onlinedocs/gcc-4.7.2/libstdc++/manual/manual/status.html#status.iso.2011)とstead_clock::is_steadyは本当ですが、あなたは--enable-libstdcxx-time=rt

でGCCをビルドする場合にのみ、その構成オプションの詳細についてはhttps://stackoverflow.com/a/12961816/981959を参照してください。 GCC 4.9あなたのOSとCライブラリがclock_gettimeのためにPOSIX単調なクロックをサポートしている場合、それは自動的に有効になりますについては

(のglibc 2.17以降でとSolaris 10、IIRCのためにGNU/Linux用真である)

ここにいます2.15

$ ./hrc 
clock::period: 0.001000 us. 
clock::is_steady: no 
Calling clock::now() 1000000 times... 
That took 0.069646 seconds. That's 69.645928 ns/iteration. 
$ ./sys 
clock::period: 0.001000 us. 
clock::is_steady: no 
Calling clock::now() 1000000 times... 
That took 0.062535 seconds. That's 62.534986 ns/iteration. 
$ ./sc 
clock::period: 0.001000 us. 
clock::is_steady: yes 
Calling clock::now() 1000000 times... 
That took 0.065684 seconds. That's 65.683730 ns/iteration. 

そしてをせずにGCC 4.7 でのglibc、GCC 4.8での結果は、AMDのPhenom II X4のの905e、2.5GHz帯に--enable-libstdcxx-time=rtで構成され、私はそれは、Linux 3.6.11を実行している、今の800MHzに絞ると思います--enable-libstdcxx-time(同じようにARMv7上のExynos5 Linux 3.4.0、glibc 2.16

clock::period: 1.000000 us. 
clock::is_steady: no 
Calling clock::now() 1000000 times... 
That took 1.089904 seconds. That's 1089.904000 ns/iteration. 
+1

あなたのアーカイブされた電子メール(http://gcc.gnu.org/ml/libstdc++/2012-05/msg00085.html)で、「GNU/Linuxの場合はまだ を使用する必要があります。 libstdC++を使用するシングルスレッドコードでパフォーマンスヒットを発生させる--enable-libstdcxx-time = rt ._ "パフォーマンスのヒットとなる操作を指定できますか?あなたが結論に到着した(つまり、あなたはプロファイルしましたか?) –

+2

そのメールの最初の段落を参照してください:その理由のいくつかまたはすべてがlibrtで定義されていますが、libstdC++の場合はGNU/Linux上に定義されていますのでlibrt.soにリンクするとlibpthread.soにリンクして__gthread_active_p )は、常にtrueを返し、シングルスレッドapps.llの追加のロックを引き起こします。libstdC++の参照カウントは、プログラムがlibpthreadにリンクするかどうかによって決まる、複数のスレッドを使用するプログラムでアトムまたはmutexを使用します。 –

7

あなたは他のプラットフォーム/コンパイラの簡単なプログラムを実行することができれば、私 は非常になります結果を知ることに興味がある。

のMac OS X 10.8、打ち鳴らす++/libcの++、-O3、2.8 GHzのコアi5:

High resolution clock 

clock::period: 0.001000 us. 
clock::is_steady: yes 
Calling clock::now() 1000000 times... 
That took 0.021833 seconds. That's 21.832827 ns/iteration. 

System clock 

clock::period: 1.000000 us. 
clock::is_steady: no 
Calling clock::now() 1000000 times... 
That took 0.041930 seconds. That's 41.930000 ns/iteration. 

Steady clock 

clock::period: 0.001000 us. 
clock::is_steady: yes 
Calling clock::now() 1000000 times... 
That took 0.021478 seconds. That's 21.477953 ns/iteration. 

steady_clocksystem_clockの異なるタイプであることが要求されています。 steady_clock::is_steadytrueである必要があります。 high_resolution_clockは、別のタイプでも、steady_clockまたはsystem_clockの別名でもかまいません。 system_clock::repは署名タイプでなければなりません。

4

GNU's siteによれば、GNU libstdC++はまだsteady_clockをサポートしていません。だからsteady_clock::is_steadyはfalseです。ここ

支持チェックリストの関連セクションである:

20.11.7.1 Class system_clock   Y 
20.11.7.2 Class steady_clock   N Support old monotonic_clock spec instead 
20.11.7.3 Class high_resolution_clock Y 
+0

ああ、そういう疑いがありました。もし私がその権利を読んでいれば、少なくともそれは単調である。 –

+2

これらのドキュメントは古くなっています.GCC 4.7では 'steady_clock'がサポートされていますが、' --enable-libstdcxx-time'でGCCをビルドした場合にのみ –

+3

コメントは単調であると言います。以前のC++ 0xドラフトの 'monotonic_clock' ...実際にはGCC 4.7以降では当てはまりませんでしたが、ドキュメントは数ヶ月先ですが、クラスは' steady_clock'と呼ばれますが 'is_steady'は' enable-libstdcxx-time'が使用されています –