14 #ifndef OR_TOOLS_UTIL_TIME_LIMIT_H_ 15 #define OR_TOOLS_UTIL_TIME_LIMIT_H_ 24 #include "absl/container/flat_hash_map.h" 25 #include "absl/memory/memory.h" 26 #include "absl/time/clock.h" 27 #include "ortools/base/commandlineflags.h" 28 #include "ortools/base/logging.h" 29 #include "ortools/base/macros.h" 30 #include "ortools/base/timer.h" 31 #include "ortools/util/running_stat.h" 32 #ifdef HAS_PERF_SUBSYSTEM 33 #include "exegesis/exegesis/itineraries/perf_subsystem.h" 34 #endif // HAS_PERF_SUBSYSTEM 122 double limit_in_seconds,
123 double deterministic_limit = std::numeric_limits<double>::infinity(),
124 double instruction_limit = std::numeric_limits<double>::infinity());
135 return absl::make_unique<TimeLimit>(
136 std::numeric_limits<double>::infinity(),
137 std::numeric_limits<double>::infinity(),
138 std::numeric_limits<double>::infinity());
145 double deterministic_limit) {
146 return absl::make_unique<TimeLimit>(
147 std::numeric_limits<double>::infinity(), deterministic_limit,
148 std::numeric_limits<double>::infinity());
158 template <
typename Parameters>
160 const Parameters& parameters) {
161 return absl::make_unique<TimeLimit>(
162 parameters.max_time_in_seconds(), parameters.max_deterministic_time(),
163 std::numeric_limits<double>::infinity());
172 instruction_limit_ = instruction_limit;
213 return std::max(0.0, deterministic_limit_ - elapsed_deterministic_time_);
227 DCHECK_LE(0.0, deterministic_duration);
228 elapsed_deterministic_time_ += deterministic_duration;
241 const char* counter_name) {
244 deterministic_counters_[counter_name] += deterministic_duration;
252 return 1e-9 * (absl::GetCurrentTimeNanos() - start_ns_);
261 return elapsed_deterministic_time_;
275 std::atomic<bool>* external_boolean_as_limit) {
276 external_boolean_as_limit_ = external_boolean_as_limit;
283 return external_boolean_as_limit_;
290 template <
typename Parameters>
300 void ResetTimers(
double limit_in_seconds,
double deterministic_limit,
301 double instruction_limit);
303 std::string GetInstructionRetiredEventName()
const {
304 return "inst_retired:any_p:u";
307 mutable int64 start_ns_;
311 const int64 safety_buffer_ns_;
312 RunningMax<int64> running_max_;
315 UserTimer user_timer_;
316 double limit_in_seconds_;
318 double deterministic_limit_;
319 double elapsed_deterministic_time_;
321 std::atomic<bool>* external_boolean_as_limit_;
323 #ifdef HAS_PERF_SUBSYSTEM 325 exegesis::PerfSubsystem perf_subsystem_;
326 #endif // HAS_PERF_SUBSYSTEM 328 double instruction_limit_;
332 absl::flat_hash_map<std::string, double> deterministic_counters_;
376 double deterministic_limit);
390 template <
typename Parameters>
392 TimeLimit* time_limit,
const Parameters& parameters) {
393 return absl::make_unique<NestedTimeLimit>(
394 time_limit, parameters.max_time_in_seconds(),
395 parameters.max_deterministic_time());
416 double instruction_limit)
417 : safety_buffer_ns_(static_cast<int64>(kSafetyBufferSeconds * 1e9)),
418 running_max_(kHistorySize),
419 external_boolean_as_limit_(nullptr) {
420 ResetTimers(limit_in_seconds, deterministic_limit, instruction_limit);
423 inline void TimeLimit::ResetTimers(
double limit_in_seconds,
424 double deterministic_limit,
425 double instruction_limit) {
426 if (external_boolean_as_limit_ !=
nullptr) {
427 *external_boolean_as_limit_ =
false;
429 elapsed_deterministic_time_ = 0.0;
430 deterministic_limit_ = deterministic_limit;
431 instruction_limit_ = instruction_limit;
433 if (FLAGS_time_limit_use_usertime) {
435 limit_in_seconds_ = limit_in_seconds;
437 #ifdef HAS_PERF_SUBSYSTEM 438 if (FLAGS_time_limit_use_instruction_count) {
439 perf_subsystem_.CleanUp();
440 perf_subsystem_.AddEvent(GetInstructionRetiredEventName());
441 perf_subsystem_.StartCollecting();
443 #endif // HAS_PERF_SUBSYSTEM 444 start_ns_ = absl::GetCurrentTimeNanos();
445 last_ns_ = start_ns_;
446 limit_ns_ = limit_in_seconds >= 1e-9 * (kint64max - start_ns_)
448 : static_cast<int64>(limit_in_seconds * 1e9) + start_ns_;
451 template <
typename Parameters>
453 ResetTimers(parameters.max_time_in_seconds(),
454 parameters.max_deterministic_time(),
455 std::numeric_limits<double>::infinity());
459 if (other ==
nullptr)
return;
463 std::numeric_limits<double>::infinity());
470 #ifdef HAS_PERF_SUBSYSTEM 471 if (FLAGS_time_limit_use_instruction_count) {
472 return perf_subsystem_.ReadCounters().GetScaledOrDie(
473 GetInstructionRetiredEventName());
475 #endif // HAS_PERF_SUBSYSTEM 480 if (external_boolean_as_limit_ !=
nullptr &&
481 external_boolean_as_limit_->load()) {
489 #ifdef HAS_PERF_SUBSYSTEM 493 #endif // HAS_PERF_SUBSYSTEM 495 const int64 current_ns = absl::GetCurrentTimeNanos();
496 running_max_.Add(std::max(safety_buffer_ns_, current_ns - last_ns_));
497 last_ns_ = current_ns;
498 if (current_ns + running_max_.GetCurrentMax() >= limit_ns_) {
499 if (FLAGS_time_limit_use_usertime) {
503 const double time_left_s = limit_in_seconds_ - user_timer_.Get();
505 limit_ns_ = static_cast<int64>(time_left_s * 1e9) + last_ns_;
518 if (limit_ns_ == kint64max)
return std::numeric_limits<double>::infinity();
519 const int64 delta_ns = limit_ns_ - absl::GetCurrentTimeNanos();
520 if (delta_ns < 0)
return 0.0;
521 if (FLAGS_time_limit_use_usertime) {
522 return std::max(limit_in_seconds_ - user_timer_.Get(), 0.0);
524 return delta_ns * 1e-9;
534 #endif // OR_TOOLS_UTIL_TIME_LIMIT_H_ void RegisterExternalBooleanAsLimit(std::atomic< bool > *external_boolean_as_limit)
Registers the external Boolean to check when LimitReached() is called.
static const double kSafetyBufferSeconds
double ReadInstructionCounter()
Returns the number of instructions executed since the creation of this object.
NestedTimeLimit(TimeLimit *base_time_limit, double limit_in_seconds, double deterministic_limit)
Creates the nested time limit.
double GetElapsedDeterministicTime() const
Returns the elapsed deterministic time since the construction of this object.
double GetInstructionsLeft()
Returns the number of instructions left to reach the limit.
bool LimitReached()
Returns true when the external limit is true, or the deterministic time is over the deterministic lim...
static std::unique_ptr< TimeLimit > Infinite()
Creates a time limit object that uses infinite time for wall time, deterministic time and instruction...
double GetElapsedTime() const
Returns the time elapsed in seconds since the construction of this object.
static std::unique_ptr< TimeLimit > FromParameters(const Parameters ¶meters)
Creates a time limit object initialized from an object that provides methods max_time_in_seconds() an...
double GetTimeLeft() const
Returns the time left on this limit, or 0 if the limit was reached (it never returns a negative value...
static std::unique_ptr< TimeLimit > FromDeterministicTime(double deterministic_limit)
Creates a time limit object that puts limit only on the deterministic time.
void AdvanceDeterministicTime(double deterministic_duration, const char *counter_name)
Advances the deterministic time.
std::atomic< bool > * ExternalBooleanAsLimit() const
Returns the current external Boolean limit.
TimeLimit * GetTimeLimit()
Returns a time limit object that represents the combination of the overall time limit and the part-sp...
DECLARE_bool(time_limit_use_usertime)
Enables changing the behavior of the TimeLimit class to use -b usertime instead of walltime.
TimeLimit & operator=(const TimeLimit &)=delete
void SetInstructionLimit(double instruction_limit)
Sets the instruction limit.
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Provides a way to nest time limits for algorithms where a certain part of the computation is bounded ...
void ResetLimitFromParameters(const Parameters ¶meters)
Sets new time limits.
static const int kHistorySize
std::string DebugString() const
Returns information about the time limit object in a human-readable form.
void AdvanceDeterministicTime(double deterministic_duration)
Advances the deterministic time.
static std::unique_ptr< NestedTimeLimit > FromBaseTimeLimitAndParameters(TimeLimit *time_limit, const Parameters ¶meters)
Creates a time limit object initialized from a base time limit and an object that provides methods ma...
double GetDeterministicTimeLeft() const
Returns the remaining deterministic time before LimitReached() returns true due to the deterministic ...
~NestedTimeLimit()
Updates elapsed deterministic time in the base time limit object.
void MergeWithGlobalTimeLimit(TimeLimit *other)
friend class ParallelTimeLimit