| | |
| |
|
| | #pragma once |
| |
|
| | #include <c10/macros/Export.h> |
| | #include <array> |
| | #include <chrono> |
| | #include <cstddef> |
| | #include <cstdint> |
| | #include <ctime> |
| | #include <functional> |
| | #include <type_traits> |
| |
|
| | #if defined(C10_IOS) && defined(C10_MOBILE) |
| | #include <sys/time.h> |
| | #endif |
| |
|
| | #if defined(__i386__) || defined(__x86_64__) || defined(__amd64__) |
| | #define C10_RDTSC |
| | #if defined(_MSC_VER) |
| | #include <intrin.h> |
| | #elif defined(__CUDACC__) || defined(__HIPCC__) |
| | #undef C10_RDTSC |
| | #elif defined(__clang__) |
| | |
| | |
| | #elif defined(__GNUC__) |
| | #include <x86intrin.h> |
| | #else |
| | #undef C10_RDTSC |
| | #endif |
| | #endif |
| |
|
| | namespace c10 { |
| |
|
| | using time_t = int64_t; |
| | using steady_clock_t = std::conditional_t< |
| | std::chrono::high_resolution_clock::is_steady, |
| | std::chrono::high_resolution_clock, |
| | std::chrono::steady_clock>; |
| |
|
| | inline time_t getTimeSinceEpoch() { |
| | auto now = std::chrono::system_clock::now().time_since_epoch(); |
| | return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count(); |
| | } |
| |
|
| | inline time_t getTime(bool allow_monotonic = false) { |
| | #if defined(C10_IOS) && defined(C10_MOBILE) |
| | |
| | |
| | |
| | struct timeval now; |
| | gettimeofday(&now, NULL); |
| | return static_cast<time_t>(now.tv_sec) * 1000000000 + |
| | static_cast<time_t>(now.tv_usec) * 1000; |
| | #elif defined(_WIN32) || defined(__MACH__) |
| | return std::chrono::duration_cast<std::chrono::nanoseconds>( |
| | steady_clock_t::now().time_since_epoch()) |
| | .count(); |
| | #else |
| | |
| | struct timespec t{}; |
| | auto mode = CLOCK_REALTIME; |
| | if (allow_monotonic) { |
| | mode = CLOCK_MONOTONIC; |
| | } |
| | clock_gettime(mode, &t); |
| | return static_cast<time_t>(t.tv_sec) * 1000000000 + |
| | static_cast<time_t>(t.tv_nsec); |
| | #endif |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | inline auto getApproximateTime() { |
| | #if defined(C10_RDTSC) |
| | return static_cast<uint64_t>(__rdtsc()); |
| | #else |
| | return getTime(); |
| | #endif |
| | } |
| |
|
| | using approx_time_t = decltype(getApproximateTime()); |
| | static_assert( |
| | std::is_same_v<approx_time_t, int64_t> || |
| | std::is_same_v<approx_time_t, uint64_t>, |
| | "Expected either int64_t (`getTime`) or uint64_t (some TSC reads)."); |
| |
|
| | |
| | class C10_API ApproximateClockToUnixTimeConverter final { |
| | public: |
| | ApproximateClockToUnixTimeConverter(); |
| | std::function<time_t(approx_time_t)> makeConverter(); |
| |
|
| | struct UnixAndApproximateTimePair { |
| | time_t t_; |
| | approx_time_t approx_t_; |
| | }; |
| | static UnixAndApproximateTimePair measurePair(); |
| |
|
| | private: |
| | static constexpr size_t replicates = 1001; |
| | using time_pairs = std::array<UnixAndApproximateTimePair, replicates>; |
| | time_pairs measurePairs(); |
| |
|
| | time_pairs start_times_; |
| | }; |
| |
|
| | } |
| |
|