The Gaudi Framework  v36r16 (ea80daf8)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
RdtscClock.h
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2020 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #pragma once
12 
13 #ifndef __x86_64__
14 # error "<Gaudi/Timers/RdtscClock.h> is only supported on x86"
15 #endif // not __x86_64__
16 
17 #include <chrono>
18 #include <functional>
19 #include <ratio>
20 #include <thread>
21 #include <x86intrin.h>
22 
23 namespace Gaudi {
24  namespace Timers {
36  template <typename Precision = std::chrono::microseconds>
37  class RdtscClock {
38  public:
39  // to meet requirements of TrivialClock:
40  typedef typename Precision::rep rep;
41  typedef typename Precision::period period;
44 
45  static constexpr bool is_steady{ true };
46 
47  // some sanity checks:
48  static_assert( period::num == 1, "The Precision of RdtscClock must be reducible to 1/N" );
50  "The Precision of RdtscClock must be at least std::chrono::milliseconds" );
51 
53  static rep calibrate() noexcept { return ticks_per_unit(); }
54 
55  static time_point now() noexcept { return time_point{ duration( __rdtsc() / ticks_per_unit() ) }; }
56 
57  private:
58  static rep ticks_per_unit() noexcept {
59  static rep ticks_per_unit = do_calibrate(); // local static guarantees thread-safety
60  return ticks_per_unit;
61  }
62 
63  static rep do_calibrate() noexcept {
64  // Calibration time and conversion factor to unit of Precision
65  static constexpr auto calibTime = std::chrono::milliseconds( 100 );
66  static constexpr auto toPrec = std::ratio_divide<std::milli, period>::num;
67 
68  // Calibrate against wall clock
70  auto t1 = __rdtsc();
71  std::this_thread::sleep_for( calibTime );
72  auto t2 = __rdtsc();
74 
75  // Calculate ticks per unit of Precision
76  auto dt_ref = std::chrono::duration_cast<std::chrono::milliseconds>( t2_ref - t1_ref ).count();
77  rep ticks_per_unit = ( t2 - t1 ) / ( dt_ref * toPrec );
78 
79  return ticks_per_unit;
80  }
81  };
82  } // namespace Timers
83 } // namespace Gaudi
Gaudi::Timers::RdtscClock::period
Precision::period period
Definition: RdtscClock.h:41
std::this_thread::sleep_for
T sleep_for(T... args)
Gaudi::Timers::RdtscClock::now
static time_point now() noexcept
Definition: RdtscClock.h:55
Gaudi::Timers::RdtscClock::duration
std::chrono::duration< rep, period > duration
Definition: RdtscClock.h:42
std::ratio_less_equal
Gaudi::Timers::RdtscClock::time_point
std::chrono::time_point< RdtscClock > time_point
Definition: RdtscClock.h:43
std::chrono::duration
Gaudi::Timers::RdtscClock::is_steady
static constexpr bool is_steady
Definition: RdtscClock.h:45
TemplatedAlg
Definition: TemplatedAlg.h:25
std::chrono::time_point
Gaudi::Timers::RdtscClock
A std::chrono compatible Clock using rdtsc as its timing source.
Definition: RdtscClock.h:37
Gaudi
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
std::ratio_divide
Gaudi::Timers::RdtscClock::ticks_per_unit
static rep ticks_per_unit() noexcept
Definition: RdtscClock.h:58
Gaudi::Timers::RdtscClock::calibrate
static rep calibrate() noexcept
Calibrate the RDTSC clock against wall time.
Definition: RdtscClock.h:53
Gaudi::Timers::RdtscClock::do_calibrate
static rep do_calibrate() noexcept
Definition: RdtscClock.h:63
t1
TemplatedAlg< int, std::vector< std::string > > t1
Definition: TemplatedAlg.cpp:21
Gaudi::Timers::RdtscClock::rep
Precision::rep rep
Definition: RdtscClock.h:40
std::chrono::high_resolution_clock::now
T now(T... args)