Warning, file /include/Gaudi/Timers/RdtscClock.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #pragma once
0012
0013 #ifndef __x86_64__
0014 # error "<Gaudi/Timers/RdtscClock.h> is only supported on x86"
0015 #else
0016
0017 # include <chrono>
0018 # include <functional>
0019 # include <ratio>
0020 # include <thread>
0021 # include <x86intrin.h>
0022
0023 namespace Gaudi {
0024 namespace Timers {
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 template <typename Precision = std::chrono::microseconds>
0037 class RdtscClock {
0038 public:
0039
0040 typedef typename Precision::rep rep;
0041 typedef typename Precision::period period;
0042 typedef std::chrono::duration<rep, period> duration;
0043 typedef std::chrono::time_point<RdtscClock> time_point;
0044
0045 static constexpr bool is_steady{ true };
0046
0047
0048 static_assert( period::num == 1, "The Precision of RdtscClock must be reducible to 1/N" );
0049 static_assert( std::ratio_less_equal<period, std::milli>(),
0050 "The Precision of RdtscClock must be at least std::chrono::milliseconds" );
0051
0052
0053 static rep calibrate() noexcept { return ticks_per_unit(); }
0054
0055 static time_point now() noexcept { return time_point{ duration( __rdtsc() / ticks_per_unit() ) }; }
0056
0057 private:
0058 static rep ticks_per_unit() noexcept {
0059 static rep ticks_per_unit = do_calibrate();
0060 return ticks_per_unit;
0061 }
0062
0063 static rep do_calibrate() noexcept {
0064
0065 static constexpr auto calibTime = std::chrono::milliseconds( 100 );
0066 static constexpr auto toPrec = std::ratio_divide<std::milli, period>::num;
0067
0068
0069 auto t1_ref = std::chrono::high_resolution_clock::now();
0070 auto t1 = __rdtsc();
0071 std::this_thread::sleep_for( calibTime );
0072 auto t2 = __rdtsc();
0073 auto t2_ref = std::chrono::high_resolution_clock::now();
0074
0075
0076 auto dt_ref = std::chrono::duration_cast<std::chrono::milliseconds>( t2_ref - t1_ref ).count();
0077 rep ticks_per_unit = ( t2 - t1 ) / ( dt_ref * toPrec );
0078
0079 return ticks_per_unit;
0080 }
0081 };
0082 }
0083 }
0084 #endif