std :: system_clock과 std :: steady_clock의 차이점은 무엇입니까?


97

std::system_clock과 의 차이점은 무엇입니까 std::steady_clock? (다른 결과 / 동작을 보여주는 예제 사례가 좋습니다).

내 목표가 (벤치 마크와 같은) 함수의 실행 시간을 정확하게 측정하는 것이라면 std::system_clock, std::steady_clock과 사이에서 가장 좋은 선택은 std::high_resolution_clock무엇일까요?


9
우선 system_clock이 일정하지 않을 수 있습니다.
James McNellis 2012

12
@CharlesSalvia 다른 플랫폼에 대해서는 말할 수 없지만 system_clockWindows에서는 안정적이지 않습니다. Windows에서 시스템 시간은 충분한 권한이있는 사용자에 의해 임의의 값으로 변경 될 수 있습니다. 또한 시간 동기화 서비스는 필요한 경우 시스템 시간을 뒤로 조정할 수 있습니다. 대부분의 다른 플랫폼에는 시스템 시간을 조정할 수있는 유사한 기능이 있습니다.
James McNellis 2015 년

3
@Charles : 내가 아는 대부분의 POSIX 상자는 비슷한 영향을받으며 사용자가 시간을 변경하면 시간이 변경됩니다.
Billy ONeal 2015 년

5
:이 질문에 대한 비디오 대답 youtube.com/watch?v=P32hvk8b13M&t=48m44s
하워드 Hinnant

1
@CharlesSalvia. 수십 개의 PC 데이터 수집 시스템의 타이밍 출력을 분석 한 내 경험에 따르면 컴퓨터의 시간은 일정하지 않습니다. Linux, Windows 및 사용 된 특정 시스템 호출은 알 수 없지만 공통점은 후속 시간 값 사이에 빈번한 음의 시간 차이입니다. 직선 시간은 표준이 아닙니다.
타이슨은 Hilmer

답변:


72

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_clocksteady_clock

예를 들어, 시스템 전체 시계는 일광 절약 시간과 같은 영향을받을 수 있으며,이 시점에서 미래의 특정 시점에 나열된 실제 시간은 실제로 과거 시간이 될 수 있습니다. (예를 들어 미국에서는 하강 시간이 1 시간 뒤로 이동하므로 같은 시간이 "두 번"경험됩니다.) 그러나 steady_clock그러한 일에 영향을받는 것은 허용되지 않습니다.

이 경우 "정상"에 대해 생각하는 또 다른 방법은 20.11.3 [time.clock.req] / 2의 표에 정의 된 요구 사항입니다.

표 59 C1C2나타낸다 시계 타입. t1t2에 의해 반환 된 값입니다 C1::now()반환 호출이 곳 t1호출이 반환하기 전에 발생 t2하고 이러한 호출 모두 전에 발생은 C1::time_point::max(). [참고 :이 수단 C1사이의 주위에 포장하지 않았다 t1t2. —end note]

표현식 : C1::is_steady
반환 값 : const bool
작동 의미론 : 이 항상 참이고 클록 틱 사이의 시간이 일정 true하다면 t1 <= t2, 그렇지 않으면 false.

그것이 그들의 차이점에 대한 모든 표준입니다.

벤치마킹을하려는 경우 가장 좋은 방법은 일 것 std::high_resolution_clock입니다. 플랫폼 QueryPerformanceCounter에서이 시계에 고해상도 타이머 (예 : Windows)를 사용할 가능성이 높기 때문 입니다. 그러나 벤치마킹하는 경우 플랫폼마다 다르게 처리하므로 벤치 마크에 플랫폼 별 타이머를 사용하는 것이 좋습니다. 예를 들어, 일부 플랫폼은 프로그램에 필요한 실제 클럭 틱 수를 결정하는 수단을 제공 할 수 있습니다 (동일한 CPU에서 실행되는 다른 프로세스와 무관). 더 좋은 방법은 실제 프로파일 러에 손을 대고 사용하는 것입니다.


1
@Charles : 표준에서 그게 어디인지 지적 하시겠습니까? 그 반대를 분명히 나타내는 것 같습니다.
Billy ONeal 2015 년

9
@Charles : 또한 POSIX 시간은 "정상"이 아닙니다. 사용자가 컴퓨터에서 시간 설정을 변경하면 POSIX 시간이 변경됩니다. 계란을 요리 할 때 4 분 동안 지속되는 타이머가 필요하면 현재 시간이 변경 되더라도 4 분 동안 지속되어야합니다. 5 일 3시에 회의 타이머를 설정 한 경우 현지 시간이 변경되면 해당 타이머를 변경해야합니다. 따라서 steady_clocksystem_clock여기 의 차이 .
Billy ONeal 2015 년

1
@ 5gon : system_clockUTC 일 필요는 없습니다 .
Billy ONeal 2015

1
@CharlesSalvia POSIX 시간은 UTC에 연결되어 있고 UTC에는 윤초가 있습니다 (참조 : en.wikipedia.org/wiki/Unix_time#Leap_seconds ). 즉, 기계의 시간을 조정하지 않더라도 C / POSIX 시간은 단조 적이 지 않을 수 있습니다.
Michael Schlottke-Lakemper

3
업데이트 (Visual Studio 2015) steady_clock의 구현이 변경되었습니다. [.....] steady_clock은 이제 QueryPerformanceCounter ()를 기반으로하며 high_resolution_clock은 이제 steady_clock의 typedef입니다. msdn.microsoft.com/en-us/library/hh874757.aspx
felix-b

47

Billy는 내가 완전히 동의하는 ISO C ++ 표준을 기반으로 훌륭한 답변을 제공했습니다. 그러나 이야기의 또 다른 측면이 있습니다. 지금은 인기있는 컴파일러를 구현할 때 이러한 클럭간에 실제로 차이가없는 것 같습니다.

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의 경우 훨씬 더 쉽습니다. 의 man 페이지를 읽고 clock_gettime위의 코드를 수정하십시오.


19
VC ++ 2012 구현은 MS의 표준 라이브러리 관리자에 의해 버그로 인정되었습니다.
ildjarn


1
부스트가 너무 부스트를 사용하여 : 크로노 비주얼 스튜디오 (14)가 해제 될 때까지 좋은이 버그를 해결하고, QueryPerformanceCounter에 사용
모하메드 엘 - Nakib을

다음은 GCC 5.3.0에서 전달되는 POSIX 호출입니다. stackoverflow.com/a/36700301/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

19

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_REALTIMEvs CLOCK_MONOTONIC설명 : CLOCK_REALTIME과 CLOCK_MONOTONIC의 차이점?


2

아마도 가장 중요한 차이점은 시작점 std::chrono:system_clock이 UNIX-epoch라고하는 1.1.1970 이라는 사실입니다 . 반면에 std::chrono::steady_clock일반적으로 PC의 부팅 시간은 측정 간격에 가장 적합합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.