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/synchronization/mutex.h" 27 #include "absl/time/clock.h" 33 #ifdef HAS_PERF_SUBSYSTEM 34 #include "exegesis/exegesis/itineraries/perf_subsystem.h" 35 #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>
161 return absl::make_unique<TimeLimit>(
163 std::numeric_limits<double>::infinity());
172 instruction_limit_ = instruction_limit;
213 return std::max(0.0, deterministic_limit_ - elapsed_deterministic_time_);
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_;
274 std::atomic<bool>* external_boolean_as_limit) {
275 external_boolean_as_limit_ = external_boolean_as_limit;
282 return external_boolean_as_limit_;
289 template <
typename Parameters>
299 void ResetTimers(
double limit_in_seconds,
double deterministic_limit,
300 double instruction_limit);
302 std::string GetInstructionRetiredEventName()
const {
303 return "inst_retired:any_p:u";
306 mutable int64_t start_ns_;
310 const int64_t safety_buffer_ns_;
311 RunningMax<int64_t> running_max_;
315 double limit_in_seconds_;
317 double deterministic_limit_;
318 double elapsed_deterministic_time_;
320 std::atomic<bool>* external_boolean_as_limit_;
322 #ifdef HAS_PERF_SUBSYSTEM 324 exegesis::PerfSubsystem perf_subsystem_;
325 #endif // HAS_PERF_SUBSYSTEM 327 double instruction_limit_;
331 absl::flat_hash_map<std::string, double> deterministic_counters_;
342 : time_limit_(
time_limit), stopped_boolean_(false) {
344 stopped_ =
time_limit->ExternalBooleanAsLimit();
345 if (stopped_ ==
nullptr) {
346 stopped_ = &stopped_boolean_;
347 time_limit->RegisterExternalBooleanAsLimit(stopped_);
352 if (stopped_ == &stopped_boolean_) {
353 time_limit_->RegisterExternalBooleanAsLimit(
nullptr);
360 absl::MutexLock lock(&mutex_);
361 return time_limit_->LimitReached();
365 absl::MutexLock lock(&mutex_);
370 absl::MutexLock lock(&mutex_);
375 absl::MutexLock lock(&mutex_);
376 time_limit_->AdvanceDeterministicTime(deterministic_duration);
380 absl::ReaderMutexLock lock(&mutex_);
381 return time_limit_->GetTimeLeft();
385 absl::ReaderMutexLock lock(&mutex_);
386 return time_limit_->GetElapsedDeterministicTime();
390 mutable absl::Mutex mutex_;
391 TimeLimit* time_limit_ ABSL_GUARDED_BY(mutex_);
392 std::atomic<bool> stopped_boolean_ ABSL_GUARDED_BY(mutex_);
393 std::atomic<bool>* stopped_ ABSL_GUARDED_BY(mutex_);
433 double deterministic_limit);
447 template <
typename Parameters>
450 return absl::make_unique<NestedTimeLimit>(
473 double instruction_limit)
474 : safety_buffer_ns_(static_cast<int64_t>(kSafetyBufferSeconds * 1e9)),
475 running_max_(kHistorySize),
476 external_boolean_as_limit_(nullptr) {
477 ResetTimers(limit_in_seconds, deterministic_limit, instruction_limit);
480 inline void TimeLimit::ResetTimers(
double limit_in_seconds,
481 double deterministic_limit,
482 double instruction_limit) {
483 elapsed_deterministic_time_ = 0.0;
484 deterministic_limit_ = deterministic_limit;
485 instruction_limit_ = instruction_limit;
487 if (absl::GetFlag(FLAGS_time_limit_use_usertime)) {
489 limit_in_seconds_ = limit_in_seconds;
491 #ifdef HAS_PERF_SUBSYSTEM 492 if (absl::GetFlag(FLAGS_time_limit_use_instruction_count)) {
493 perf_subsystem_.CleanUp();
494 perf_subsystem_.AddEvent(GetInstructionRetiredEventName());
495 perf_subsystem_.StartCollecting();
497 #endif // HAS_PERF_SUBSYSTEM 498 start_ns_ = absl::GetCurrentTimeNanos();
499 last_ns_ = start_ns_;
500 limit_ns_ = limit_in_seconds >= 1e-9 * (
kint64max - start_ns_)
502 : static_cast<int64_t>(limit_in_seconds * 1e9) + start_ns_;
505 template <
typename Parameters>
509 std::numeric_limits<double>::infinity());
513 if (other ==
nullptr)
return;
517 std::numeric_limits<double>::infinity());
524 #ifdef HAS_PERF_SUBSYSTEM 525 if (absl::GetFlag(FLAGS_time_limit_use_instruction_count)) {
526 return perf_subsystem_.ReadCounters().GetScaledOrDie(
527 GetInstructionRetiredEventName());
529 #endif // HAS_PERF_SUBSYSTEM 534 if (external_boolean_as_limit_ !=
nullptr &&
535 external_boolean_as_limit_->load()) {
543 #ifdef HAS_PERF_SUBSYSTEM 547 #endif // HAS_PERF_SUBSYSTEM 549 const int64_t current_ns = absl::GetCurrentTimeNanos();
550 running_max_.
Add(
std::max(safety_buffer_ns_, current_ns - last_ns_));
551 last_ns_ = current_ns;
552 if (current_ns + running_max_.
GetCurrentMax() >= limit_ns_) {
553 if (absl::GetFlag(FLAGS_time_limit_use_usertime)) {
557 const double time_left_s = limit_in_seconds_ - user_timer_.
Get();
559 limit_ns_ = static_cast<int64_t>(time_left_s * 1e9) + last_ns_;
572 if (limit_ns_ ==
kint64max)
return std::numeric_limits<double>::infinity();
573 const int64_t delta_ns = limit_ns_ - absl::GetCurrentTimeNanos();
574 if (delta_ns < 0)
return 0.0;
575 if (absl::GetFlag(FLAGS_time_limit_use_usertime)) {
576 return std::max(limit_in_seconds_ - user_timer_.
Get(), 0.0);
578 return delta_ns * 1e-9;
588 #endif // OR_TOOLS_UTIL_TIME_LIMIT_H_
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
ModelSharedTimeLimit * time_limit
TimeLimit * GetTimeLimit()
Returns a time limit object that represents the combination of the overall time limit and the part-sp...
ABSL_DECLARE_FLAG(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
double GetDeterministicTimeLeft() const
Returns the remaining deterministic time before LimitReached() returns true due to the deterministic ...
void UpdateLocalLimit(TimeLimit *local_limit)
void ResetLimitFromParameters(const Parameters ¶meters)
Sets new time limits.
NestedTimeLimit(TimeLimit *base_time_limit, double limit_in_seconds, double deterministic_limit)
Creates the nested time limit.
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...
static std::unique_ptr< TimeLimit > FromDeterministicTime(double deterministic_limit)
Creates a time limit object that puts limit only on the deterministic time.
static const int64_t kint64max
void AdvanceDeterministicTime(double deterministic_duration, const char *counter_name)
Advances the deterministic time.
std::string DebugString() const
Returns information about the time limit object in a human-readable form.
~NestedTimeLimit()
Updates elapsed deterministic time in the base time limit object.
bool LimitReached() const
void SetInstructionLimit(double instruction_limit)
Sets the instruction limit.
std::atomic< bool > * ExternalBooleanAsLimit() const
Returns the current external Boolean limit.
void AdvanceDeterministicTime(double deterministic_duration)
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...
void MergeWithGlobalTimeLimit(TimeLimit *other)
SharedTimeLimit(TimeLimit *time_limit)
double GetTimeLeft() const
double GetElapsedDeterministicTime() const
Returns the elapsed deterministic time since the construction of this object.
double GetElapsedTime() const
Returns the time elapsed in seconds since the construction of this object.
double GetTimeLeft() const
Returns the time left on this limit, or 0 if the limit was reached (it never returns a negative value...
bool LimitReached()
Returns true when the external limit is true, or the deterministic time is over the deterministic lim...
Provides a way to nest time limits for algorithms where a certain part of the computation is bounded ...
void AdvanceDeterministicTime(double deterministic_duration)
Advances the deterministic time.
double GetInstructionsLeft()
Returns the number of instructions left to reach the limit.
#define DCHECK_LE(val1, val2)
friend class ParallelTimeLimit
void RegisterExternalBooleanAsLimit(std::atomic< bool > *external_boolean_as_limit)
Registers the external Boolean to check when LimitReached() is called.
Collection of objects used to extend the Constraint Solver library.
static const int kHistorySize
double GetElapsedDeterministicTime() const
static const double kSafetyBufferSeconds
double ReadInstructionCounter()
Returns the number of instructions executed since the creation of this object.
static std::unique_ptr< TimeLimit > Infinite()
Creates a time limit object that uses infinite time for wall time, deterministic time and instruction...