違いは何ですか std::system_clock
およびstd::steady_clock
? (異なる結果/動作を示す例は素晴らしいでしょう)。
私の目標が関数の実行時間を正確に測定することである場合(ベンチマークなど)、std::system_clock
、std::steady_clock
およびstd::high_resolution_clock
?
N3376から:
20.11.7.1 [time.clock.system]/1:
クラス_
system_clock
_のオブジェクトは、システム全体のリアルタイムクロックからのウォールクロック時間を表します。
20.11.7.2 [time.clock.steady]/1:
クラス_
steady_clock
_のオブジェクトは、_time_point
_の値が物理時間の進行に伴って決して減少せず、_time_point
_の値がリアルタイムに対して一定の割合で進むクロックを表します。つまり、クロックが調整されない場合があります。
20.11.7.3 [time.clock.hires]/1:
クラス_
high_resolution_clock
_のオブジェクトは、ティック周期が最短のクロックを表します。 _high_resolution_clock
_は、_system_clock
_または_steady_clock
_の同義語です。
たとえば、システム全体の時計は夏時間などの影響を受ける可能性があり、その時点で将来のある時点でリストされる実際の時間は実際には過去の時間になる可能性があります。 (たとえば、米国では、フォールタイムが1時間戻るため、同じ時間が「2回」発生します)ただし、_steady_clock
_はそのようなことによる影響を受けません。
この場合の「定常」に関する別の考え方は、20.11.3 [time.clock.req]/2の表に定義されている要件にあります。
表59では、_
C1
_および_C2
_はクロックタイプを示します。 _t1
_および_t2
_はC1::now()
によって返される値です。ここで_t1
_を返す呼び出しは_t2
_を返す呼び出しの前に発生し、これらの呼び出しは両方ともC1::time_point::max()
。 [注:これは、_C1
_が_t1
_と_t2
_の間でラップアラウンドしなかったことを意味します。 —注を終了]式:_
C1::is_steady
_
戻り値:_const bool
_
操作上のセマンティクス:_t1 <= t2
_が常にtrueで、クロックティック間の時間が一定の場合はtrue
、そうでない場合はfalse
。
これが標準の違いです。
プラットフォームでこのクロックに高解像度タイマー(WindowsではQueryPerformanceCounter
など)を使用している可能性が高いため、ベンチマークを実行する場合、おそらく最善の方法は_std::high_resolution_clock
_になります。ただし、ベンチマークを行う場合は、プラットフォームごとに異なる処理を行うため、ベンチマークにプラットフォーム固有のタイマーを使用することを実際に検討する必要があります。たとえば、プラットフォームによっては、プログラムが必要とする実際のクロックティック数を決定する手段を提供する場合があります(同じCPUで実行されている他のプロセスとは無関係です)。さらに良いのは、実際のプロファイラーを手に入れて使用することです。
Billyは、私が完全に同意するISO C++標準に基づいた素晴らしい回答を提供しました。しかし、物語にはもう1つの側面があります-実生活です。現在、一般的なコンパイラの実装では、これらのクロックの間に実際に違いはないようです:
gcc 4.8:
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
...
#else
typedef system_clock steady_clock;
#endif
typedef system_clock high_resolution_clock;
Visual Studio 2012:
class steady_clock : public system_clock
{ // wraps monotonic clock
public:
static const bool is_monotonic = true; // retained
static const bool is_steady = true;
};
typedef system_clock high_resolution_clock;
Gccの場合は、is_steady
をチェックするだけで安定したクロックを処理しているかどうかを確認でき、それに応じて動作します。しかし、VS2012はここで少しチートしているようです:-)
高精度のクロックが必要な場合は、C++ 11の公式クロックインターフェイスに準拠する独自のクロックを作成し、実装が追いつくのを待つことをお勧めします。 OS固有のAPIをコードで直接使用するよりもはるかに優れたアプローチです。 Windowsの場合、次のようにできます。
// Self-made Windows QueryPerformanceCounter based C++11 API compatible clock
struct qpc_clock {
typedef std::chrono::nanoseconds duration; // nanoseconds resolution
typedef duration::rep rep;
typedef duration::period period;
typedef std::chrono::time_point<qpc_clock, duration> time_point;
static bool is_steady; // = true
static time_point now()
{
if(!is_inited) {
init();
is_inited = true;
}
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
return time_point(duration(static_cast<rep>((double)counter.QuadPart / frequency.QuadPart *
period::den / period::num)));
}
private:
static bool is_inited; // = false
static LARGE_INTEGER frequency;
static void init()
{
if(QueryPerformanceFrequency(&frequency) == 0)
throw std::logic_error("QueryPerformanceCounter not supported: " + std::to_string(GetLastError()));
}
};
Linuxではさらに簡単です。 clock_gettime
のmanページを読んで、上記のコードを修正してください。
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
_次に、_CLOCK_REALTIME
_対_CLOCK_MONOTONIC
_について説明します。 CLOCK_REALTIMEとCLOCK_MONOTONICの違い?