105

std::system_clockとはどう違いstd::steady_clockますか?(さまざまな結果/動作を示す例は素晴らしいでしょう)。

関数の実行時間を (ベンチマークのように) 正確に測定することが私の目標である場合、 と の間の最良の選択は何でしょstd::system_clockstd::steady_clockstd::high_resolution_clock?

4

5 に答える 5

77

N3376から:

20.11.7.1 [time.clock.system] / 1:

クラスのオブジェクトはsystem_clock、システム全体のリアルタイムクロックからの実時間を表します。

20.11.7.2 [time.clock.steady] / 1:

クラスのオブジェクトは、物理的な時間が進むにつれて値が減少することはなく、リアルタイムに対して一定の速度で値が進むsteady_clockクロックを表します。つまり、時計が調整されていない可能性があります。time_pointtime_point

20.11.7.3 [time.clock.hires] / 1:

クラスのオブジェクトはhigh_resolution_clock、ティック周期が最も短いクロックを表します。またはhigh_resolution_clockの同義語である可能性があります。system_clocksteady_clock

たとえば、システム全体の時計は、夏時間のようなものの影響を受ける可能性があります。その時点で、将来のある時点でリストされている実際の時刻は、実際には過去の時刻である可能性があります。(たとえば、米国では、秋に1時間戻るため、同じ時間が「2回」発生します)ただし、steady_clockこのような影響を受けることは許可されていません。

この場合の「定常」についての別の考え方は、20.11.3 [time.clock.req]/2の表で定義されている要件にあります。

表59で、クロックタイプC1を示します。およびは、呼び出しが戻る前に呼び出しが返される場所によって返される値であり、これらの呼び出しは両方とも。の前に発生します。[注:これは、との間でラップアラウンドしなかったことを意味します。—エンドノート] C2t1t2C1::now()t1t2C1::time_point::max()C1t1t2

式:C1::is_steady
戻り値:const bool
操作的意味論:truet1 <= t2常にtrueであり、クロックティック間の時間が一定である場合、それ以外の場合はfalse

標準の違いはこれだけです。

ベンチマークを実行する場合はstd::high_resolution_clock、プラットフォームがこのクロックに高解像度タイマー(QueryPerformanceCounterWindowsなど)を使用している可能性が高いため、おそらく最善の策です。ただし、ベンチマークを行う場合は、プラットフォームごとに処理方法が異なるため、ベンチマークにプラットフォーム固有のタイマーを使用することを検討する必要があります。たとえば、一部のプラットフォームでは、プログラムに必要な実際のクロックティック数を決定する手段が提供される場合があります(同じCPUで実行されている他のプロセスとは関係ありません)。さらに良いことに、実際のプロファイラーを手に入れて使用してください。

于 2012-11-07T04:54:57.180 に答える
47

ビリーは、私が完全に同意するISOC++標準に基づいた素晴らしい答えを提供しました。しかし、話には別の側面があります。それは実生活です。今のところ、人気のあるコンパイラの実装では、これらのクロックに実際には違いはないようです。

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上記のコードを変更してください。

于 2012-11-07T09:13:17.257 に答える