Realm
A distributed, event-based tasking library
Loading...
Searching...
No Matches
timers.h
Go to the documentation of this file.
1/*
2 * Copyright 2025 Stanford University, NVIDIA Corporation
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18// clocks, timers for Realm
19
20#ifndef REALM_TIMERS_H
21#define REALM_TIMERS_H
22
23#include "realm/realm_config.h"
24
25#include "realm/atomics.h"
26
27#include <cstdint>
28
29#if !defined(REALM_TIMERS_USE_RDTSC) && (defined(__i386__) || defined(__x86_64__) || \
30 defined(__aarch64__) || defined(__arm__))
31#define REALM_TIMERS_USE_RDTSC 1
32#endif
33
34namespace Realm {
35
36 // Clock provides (static) methods for getting the current time, which can be either:
37 // relative (default) - time since the runtime was initialized, synchronized between
38 // all nodes
39 // absolute - system time reported by the OS, which may not be well
40 // synchronized
41 // between nodes
42 //
43 // The time may be requested in one of three units:
44 // seconds - uses a double to store fractional seconds
45 // microseconds - uses a 64-bit integer, no fractional microseconds
46 // nanoseconds - uses a 64-bit integer, no fractional nanoseconds
47 //
48 // Also provided is the "native" time, which is ideally super-low-overhead
49 // to query (e.g. reading a cpu time stampe counter), but isn't necessarily
50 // in units of nanoseconds, nor is it synchronized between processes
52 public:
53 static double current_time(bool absolute = false);
54 static long long current_time_in_microseconds(bool absolute = false);
55 static long long current_time_in_nanoseconds(bool absolute = false);
56
57 // the "zero time" is the offset between absolute and relative time on THIS node
58 // and is stored at nanosecond granularity
59 static long long get_zero_time(void);
60 // set_zero_time() should only be called by the runtime init code
61 static void set_zero_time(void);
62
63 // inlined version when we're using CPU time stamp counter
64 static uint64_t native_time();
65
66 // conversion between native and nanoseconds
67 static uint64_t native_to_nanoseconds_absolute(uint64_t native);
68 static uint64_t nanoseconds_to_native_absolute(uint64_t nanoseconds);
69 static int64_t native_to_nanoseconds_delta(int64_t d_native);
70 static int64_t nanoseconds_to_native_delta(int64_t d_nanoseconds);
71
72 // initialization/calibration of timing
73 static void calibrate(int use_cpu_tsc /*1=yes, 0=no, -1=dont care*/,
74 uint64_t force_cpu_tsc_freq);
75
76 // return the accumulated realm timer error since calibration (in nanoseconds,
77 // positive indicates realm timer is faster) relative to system clock
78 static long long get_calibration_error();
79
81 public:
82 // defaults to identity conversion
84
85 // learns an affine translation between two timescales based on two
86 // samples from each timescale (ta1 and tb1 should be the "same time",
87 // and ta2 and tb2 should be a (later) "same time")
88 // fails if the translation cannot be represented (i.e. if the
89 // time intervals differ by a factor of more than 2^32)
90 bool set(uint64_t ta1, uint64_t tb1, uint64_t ta2, uint64_t tb2);
91
92 // adjusts the affine translation to maintain the same slope but pass
93 // through a specified (ta, tb) pair
94 void adjust(uint64_t ta, uint64_t tb);
95
96 // conversion of absolute times ("forward" = A->B, "reverse" = B-A)
97 uint64_t convert_forward_absolute(uint64_t ta);
98 uint64_t convert_reverse_absolute(uint64_t tb);
99
100 // conversion of time deltas (slightly cheaper, but must fit in int64_t)
101 int64_t convert_forward_delta(int64_t da);
102 int64_t convert_reverse_delta(int64_t db);
103
104 protected:
105 uint64_t a_zero, b_zero, slope_a_to_b, slope_b_to_a;
106 };
107
108 protected:
109#if REALM_TIMERS_USE_RDTSC
110 // Raw timestamp counter (in ticks of a given frequency)
111 static uint64_t raw_cpu_tsc(void);
112 // Raw timestamp counter frequency (in Hz) or zero if the frequency needs to
113 // be estimated
114 static uint64_t raw_cpu_tsc_freq(void);
115#endif
116
117 // slower function-call version of native_time for platform portability
118 static uint64_t native_time_slower();
119
120 static uint64_t zero_time;
122#if REALM_TIMERS_USE_RDTSC
123 static bool cpu_tsc_enabled;
124#endif
125 };
126
127 // a central theme for a responsive runtime is to place limits on how long
128 // is spent doing any one task - this is described using a TimeLimit object
129 class TimeLimit {
130 public:
131 // default constructor generates a time limit infinitely far in the future
133
134 // these constructors describe a limit in terms of Realm's clock
135 static TimeLimit absolute(long long absolute_time_in_nsec,
136 atomic<bool> *_interrupt_flag = 0);
137 static TimeLimit relative(long long relative_time_in_nsec,
138 atomic<bool> *_interrupt_flag = 0);
139
140 // often the desired time limit is "idk, something responsive", so
141 // have a common way to pick a completely-made-up number
143
144 bool is_expired() const;
145 bool will_expire(long long additional_nsec) const;
146
147 protected:
148 uint64_t limit_native;
150 };
151
152 class Logger;
153
154 // a Timestamp is a convenient way to record timestamps or measure time spent within a
155 // given C++ scope
156 class TimeStamp {
157 public:
158 TimeStamp(const char *_message, bool _difference, Logger *_logger = 0);
160
161 protected:
162 const char *message;
165 uint64_t start_native;
166 };
167
168}; // namespace Realm
169
170#include "realm/timers.inl"
171
172#endif // ifndef REALM_TIMERS_H
Definition timers.h:80
bool set(uint64_t ta1, uint64_t tb1, uint64_t ta2, uint64_t tb2)
int64_t convert_reverse_delta(int64_t db)
void adjust(uint64_t ta, uint64_t tb)
uint64_t convert_forward_absolute(uint64_t ta)
uint64_t convert_reverse_absolute(uint64_t tb)
int64_t convert_forward_delta(int64_t da)
uint64_t a_zero
Definition timers.h:105
Definition timers.h:51
static long long current_time_in_microseconds(bool absolute=false)
static uint64_t zero_time
Definition timers.h:120
static uint64_t nanoseconds_to_native_absolute(uint64_t nanoseconds)
static void set_zero_time(void)
static uint64_t native_time_slower()
static double current_time(bool absolute=false)
static TimescaleConverter native_to_nanoseconds
Definition timers.h:121
static int64_t native_to_nanoseconds_delta(int64_t d_native)
static long long get_zero_time(void)
static int64_t nanoseconds_to_native_delta(int64_t d_nanoseconds)
static long long current_time_in_nanoseconds(bool absolute=false)
static void calibrate(int use_cpu_tsc, uint64_t force_cpu_tsc_freq)
static uint64_t native_to_nanoseconds_absolute(uint64_t native)
static uint64_t native_time()
static long long get_calibration_error()
Definition logging.h:52
Definition timers.h:129
bool will_expire(long long additional_nsec) const
static TimeLimit relative(long long relative_time_in_nsec, atomic< bool > *_interrupt_flag=0)
uint64_t limit_native
Definition timers.h:148
static TimeLimit absolute(long long absolute_time_in_nsec, atomic< bool > *_interrupt_flag=0)
atomic< bool > * interrupt_flag
Definition timers.h:149
bool is_expired() const
static TimeLimit responsive()
Definition timers.h:156
Logger * logger
Definition timers.h:164
TimeStamp(const char *_message, bool _difference, Logger *_logger=0)
bool difference
Definition timers.h:163
const char * message
Definition timers.h:162
uint64_t start_native
Definition timers.h:165
Definition atomics.h:31
#define REALM_PUBLIC_API
Definition compiler_support.h:217
Definition activemsg.h:38