1. ホーム
  2. c

[解決済み] Linux で時間を計測する - time vs clock vs getrusage vs clock_gettime vs gettimeofday vs timespec_get?

2022-04-25 06:44:32

質問

タイミング機能のうち time , clock getrusage , clock_gettime , gettimeofdaytimespec_get どのような状況でそれらを使用しなければならないかを知るために、それらがどのように実装され、どのような戻り値であるかを明確に理解したいのです。

まず、以下のような関数を分類する必要があります。 壁掛け時計の値 を返す関数と比較します。 プロセスまたはスレッドの値 . gettimeofday は壁掛け時計の値を返します。 clock_gettime 壁掛け時計の値を返す または プロセスまたはスレッドの値は Clock パラメータに渡されます。 getrusageclock は処理値を返します。

次に、これらの関数の実装と、その結果としての精度に関する質問です。これらの関数は、どのようなハードウェアまたはソフトウェアのメカニズムを使用しているのでしょうか。

と思われます。 getrusage はカーネルティック(通常1msの長さ)のみを使用し、結果としてmsより正確な値を得ることはできません。これは正しいのでしょうか? では getimeofday 関数は、利用可能な最も正確なハードウェアを使用しているようです。その結果、最近のハードウェアでは、その精度は通常マイクロ秒(APIの関係でそれ以上にはならない)です。 では clock manページには「近似値」と書かれていますが、どういう意味ですか? また clock_gettime APIはナノ秒単位ですが、ハードウェアが許せば、これだけの精度が出せるということでしょうか?単調性はどうなのでしょうか?

その他の機能はありますか?

解決方法は?

問題は、CやC++で利用できる時間関数は数種類あり、その中には実装によって動作が異なるものがあることです。 また、中途半端な答えが多く出回っている。 時計関数の一覧とそのプロパティをまとめれば、この問題に適切に答えられるだろう。 手始めに、私たちが求めているのはどのような特性なのかを聞いてみましょう。あなたの投稿を見ると、私は提案します。

  • 時計が計測している時間は何時ですか?(実時間、ユーザー時間、システム時間、あるいは壁掛け時計など?)
  • クロックの精度は?(s、ms、µs、またはそれ以上?)
  • クロックは何秒後にラップアラウンドしますか?または、それを避けるための何らかのメカニズムがあるのでしょうか?
  • 時計は単調ですか、それともシステム時刻の変更(NTP、タイムゾーン、サマータイム、ユーザーによるものなど)に応じて変更されますか?
  • 上記は実装によってどのように違うのですか?
  • 特定の機能は廃止されているか、非標準であるか、など。

リストを始める前に、壁掛け時計の時刻は、タイムゾーンの変更、サマータイムの変更、壁掛け時計がNTPで同期されている場合などに変化するのに対し、正しい時刻であることはほとんどないことを指摘しておきたいと思います。 イベントのスケジュールやパフォーマンスのベンチマークに時間を使用する場合は、これらのいずれもが良いことではありません。本当に良いのは、その名の通り、壁(またはデスクトップ)の時計としてだけなのです。

LinuxとOS Xの時計について、これまで私が見つけたものは以下の通りです。

  • time() はOSの壁時計の時刻を秒単位で返します。
  • clock() は、ユーザ時刻とシステム時刻の合計を返すようです。C89以降に存在する。一時期、これはCPU時間をサイクル単位で表すとされていましたが、現代の標準では POSIXのように CLOCKS_PER_SECは1000000であることが要求されており、最大で1μsの精度が得られます。私のシステムでの精度は確かに1µsです。 このクロックはトップアウトするとラップアラウンドします(これは通常 ~2^32 ticks 後に起こりますが、1 MHz のクロックとしてはそれほど長くはありません)。 man clock によると、glibc 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)でもテストしましたが、そこでの精度はわずか1msでした。
  • gettimeofday() は壁掛け時計の時刻を(公称)μs精度で返します。私のシステムでは、この時計はµsの精度を持っているように見えますが、これは保証されていません。 システムクロックの分解能はハードウェアに依存します。 . POSIX.1-2008 には、次のように書かれています。 アプリケーションは clock_gettime() 関数の代わりに、旧式の gettimeofday() function"なので、手を出さない方がいいでしょう。Linux x86で実装している システムコールとして .
  • mach_absolute_time() は、OS Xで超高解像度(ns)タイミングを実現するためのオプションです。私のシステムでは、これは確かにnsの分解能を与えています。原理的にはこのクロックは折り返しになりますが、64ビットの符号なし整数を使用してnsを格納しているので、実際には折り返しは問題にならないはずです。移植性には疑問があります。
  • ハイブリッド関数を書いてみた をベースに このスニペット は、Linux と OS X の両方で ns 精度を得るために、Linux でコンパイルした場合は clock_gettime を、OS X でコンパイルした場合は Mach timer を使用します。

上記は、特に指定がない限り、すべてLinuxとOS Xの両方に存在します。上記における "私のシステム"は、OS X 10.8.3 と MacPortsからのGCC 4.7.2 を実行しているAppleです。

最後に、上記のリンクの他に参考になった文献を紹介します。


更新情報 : OS X用です。 clock_gettime は、10.12(Sierra)より実装されました。また、POSIX系とBSD系(OS Xなど)のプラットフォームでは、共通して rusage.ru_utime 構造体フィールド