163

タイミング関数 、timeclock getrusage、の中でclock_gettime、どのような状況で使用する必要があるかを知るために、それらがどのように実装され、どのような戻り値が返されるかを明確に理解したいと思いますgettimeofdaytimespec_get

まず、壁時計の値を返す関数を、プロセスまたはスレッドの値を返す関数と比較して分類する必要があります。gettimeofday壁時計の値を返し、渡されたパラメータに応じてclock_gettime壁時計の値またはプロセスまたはスレッドの値を返します。プロセス値を返します。Clockgetrusageclock

次に、2 番目の質問は、これらの関数の実装と、その結果としての精度に関するものです。これらの機能が使用するハードウェアまたはソフトウェアのメカニズム。

カーネル ティック (通常は 1 ミリ秒の長さ) のみを使用しているようでgetrusage、その結果、ミリ秒よりも正確になることはありません。そうですか?次に、getimeofday関数は利用可能な最も正確な基盤となるハードウェアを使用しているようです。結果として、その精度は通常、最近のハードウェアではマイクロ秒 (API のためにそれ以上になることはありません) です。についてはどうですかclock、マニュアルページでは「近似」について述べていますが、それはどういう意味ですか? API はナノ秒単位ですclock_gettimeが、基盤となるハードウェアで許可されていれば、それほど正確にできるということですか? 単調性はどうですか?

他に機能はありますか?

4

2 に答える 2

211

問題は、C および C++ で使用できるいくつかの異なる時間関数があり、それらのいくつかは実装間で動​​作が異なることです。中途半端な回答もたくさん出回っています。クロック関数のリストとそのプロパティをコンパイルすると、質問に適切に答えることができます。まず、探している関連プロパティが何であるかを尋ねてみましょう。あなたの投稿を見て、私は提案します:

  • 時計は何時を計っていますか?(本物、ユーザー、システム、またはそうでないことを願っていますが、掛け時計?)
  • 時計の精度は?(秒、ミリ秒、マイクロ秒、またはそれより速い?)
  • 時計が一巡するのは何時間後ですか。または、これを回避するためのメカニズムはありますか?
  • 時計は単調ですか、それともシステム時刻の変更 (NTP、タイム ゾーン、夏時間、ユーザーによるものなど) に伴って変化しますか?
  • 上記は実装間でどのように異なりますか?
  • 特定の機能が廃止されたり、非標準になったりしていませんか?

リストを開始する前に、タイムゾーンの変更、夏時間の変更、または壁時計が NTP によって同期されている場合は、壁時計の時間が使用するのに適切な時間になることはめったにないことを指摘したいと思います。イベントのスケジュール設定やパフォーマンスのベンチマークに時間を使用している場合、これらのことはどれも良いことではありません。名前が示すように、壁 (またはデスクトップ) の時計にのみ適しています。

Linux と OS X の時計についてこれまでに見つけたものは次のとおりです。

  • time()OS からのウォールクロック時間を秒単位の精度で返します。
  • clock()ユーザー時間とシステム時間の合計を返すようです。C89 以降に存在します。かつて、これはサイクル単位の CPU 時間であると想定されていましたが、POSIX などの最新の標準では、CLOCKS_PER_SEC を 1000000 にする必要があり、可能な最大精度は 1 µs です。私のシステムの精度は確かに 1 µs です。このクロックは、上限に達するとラップアラウンドします (これは通常、1 MHz クロックとしてはそれほど長くない ~2^32 ティック後に発生します)。man clockglibc 2.18以降clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)、Linuxで実装されていると言います。
  • clock_gettime(CLOCK_MONOTONIC, ...)ナノ秒の分解能を提供し、単調です。「秒」と「ナノ秒」は別々に保存され、それぞれが 32 ビット カウンターに格納されていると思います。したがって、何十年もの稼働時間の後にラップアラウンドが発生します。これは非常に優れた時計のように見えますが、残念ながら OS X ではまだ利用できません。POSIX 7 ではオプションの拡張機能として説明さCLOCK_MONOTONICれています。
  • getrusage()私の状況にとって最良の選択であることが判明しました。ユーザー時刻とシステム時刻を別々に報告し、ラップアラウンドしません。私のシステムの精度は 1 µs ですが、Linux システム (Red Hat 4.1.2-48 with GCC 4.1.2) でもテストしたところ、精度はわずか 1 ms でした。
  • gettimeofday()(名目上) µs の精度でウォールクロック時間を返します。私のシステムでは、このクロックは µs の精度を持っているように見えますが、「システム クロックの分解能はハードウェアに依存する」ため、これは保証されません。POSIX.1-2008によると. 「アプリケーションは廃止されたclock_gettime()関数の代わりに関数を使用する必要がありgettimeofday()ます」ので、使用しないでください。Linux x86 に実装されており、システム コールとして実装されています。
  • mach_absolute_time()は、OS X での非常に高い解像度 (ns) のタイミングのオプションです。私のシステムでは、これにより実際に ns の解像度が得られます。原則として、このクロックはラップ アラウンドしますが、64 ビットの符号なし整数を使用して ns を格納しているため、ラップ アラウンドは実際には問題になりません。携帯性は疑問です。
  • Linux と OS X の両方で精度 ns を取得するために、Linux でコンパイルする場合は clock_gettime を使用し、OS X でコンパイルする場合は Mach タイマーを使用するこのスニペットに基づいてハイブリッド関数を作成しました。

上記のすべては、特に明記されていない限り、Linux と OS X の両方に存在します。上記の「私のシステム」は、MacPorts の GCC 4.7.2 で OS X 10.8.3 を実行している Apple です。

最後に、上記のリンクに加えて、私が参考にした参考文献のリストを以下に示します。


更新: OS X の場合、clock_gettime10.12 (Sierra) で実装されました。また、POSIX と BSD ベースのプラットフォーム (OS X など) の両方がrusage.ru_utimestruct フィールドを共有します。

于 2012-09-18T15:45:58.677 に答える
19

C11timespec_get

使用例: https://stackoverflow.com/a/36095407/895245

返される最大精度はナノ秒ですが、実際の精度は実装で定義されており、これよりも小さい可能性があります。

CPU使用率ではなく、経過時間を返します。

glibc 2.21 では以下sysdeps/posix/timespec_get.cに実装されており、次の場所に直接転送されます。

clock_gettime (CLOCK_REALTIME, ts) < 0)

clock_gettimeおよびCLOCK_REALTIMEPOSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.htmlでありman clock_gettime、プログラムの実行中にシステム時間設定を変更すると、この測定値が不連続になる可能性があると述べています。

C++11 クロノ

私たちはそれに取り組んでいるので、それらもカバーしましょう: http://en.cppreference.com/w/cpp/chrono

GCC 5.3.0 (C++ stdlib は GCC ソース内にあります):

  • high_resolution_clockのエイリアスですsystem_clock
  • system_clock利用可能な次の最初のものに転送します。
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock利用可能な次の最初のものに転送します。
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

質問: std::system_clock と std::steady_clock の違いは?

CLOCK_REALTIMEvs CLOCK_MONOTONIC: CLOCK_REALTIME と CLOCK_MONOTONIC の違いは?

于 2016-04-18T17:14:12.753 に答える