14 #ifndef OR_TOOLS_UTIL_TIME_LIMIT_H_ 15 #define OR_TOOLS_UTIL_TIME_LIMIT_H_ 24 #include "absl/base/port.h" 25 #include "absl/container/flat_hash_map.h" 26 #include "absl/memory/memory.h" 27 #include "absl/synchronization/mutex.h" 28 #include "absl/time/clock.h" 34 #ifdef HAS_PERF_SUBSYSTEM 35 #include "exegesis/exegesis/itineraries/perf_subsystem.h" 36 #endif // HAS_PERF_SUBSYSTEM 123 double limit_in_seconds,
124 double deterministic_limit = std::numeric_limits<double>::infinity(),
125 double instruction_limit = std::numeric_limits<double>::infinity());
136 return absl::make_unique<TimeLimit>(
137 std::numeric_limits<double>::infinity(),
138 std::numeric_limits<double>::infinity(),
139 std::numeric_limits<double>::infinity());
146 double deterministic_limit) {
147 return absl::make_unique<TimeLimit>(
148 std::numeric_limits<double>::infinity(), deterministic_limit,
149 std::numeric_limits<double>::infinity());
159 template <
typename Parameters>
162 return absl::make_unique<TimeLimit>(
164 std::numeric_limits<double>::infinity());
173 instruction_limit_ = instruction_limit;
214 return std::max(0.0, deterministic_limit_ - elapsed_deterministic_time_);
229 elapsed_deterministic_time_ += deterministic_duration;
242 const char* counter_name) {
245 deterministic_counters_[counter_name] += deterministic_duration;
253 return 1e-9 * (absl::GetCurrentTimeNanos() - start_ns_);
262 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_t start_ns_;
311 const int64_t safety_buffer_ns_;
312 RunningMax<int64_t> running_max_;
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_;
343 : time_limit_(
time_limit), stopped_boolean_(false) {
345 stopped_ =
time_limit->ExternalBooleanAsLimit();
346 if (stopped_ ==
nullptr) {
347 stopped_ = &stopped_boolean_;
348 time_limit->RegisterExternalBooleanAsLimit(stopped_);
353 if (stopped_ == &stopped_boolean_) {
354 time_limit_->RegisterExternalBooleanAsLimit(
nullptr);
361 absl::MutexLock lock(&mutex_);
362 return time_limit_->LimitReached();
366 absl::MutexLock lock(&mutex_);
371 absl::MutexLock lock(&mutex_);
376 absl::MutexLock lock(&mutex_);
377 time_limit_->AdvanceDeterministicTime(deterministic_duration);
381 absl::ReaderMutexLock lock(&mutex_);
382 return time_limit_->GetTimeLeft();
386 absl::ReaderMutexLock lock(&mutex_);
387 return time_limit_->GetElapsedDeterministicTime();
391 mutable absl::Mutex mutex_;
392 TimeLimit* time_limit_ ABSL_GUARDED_BY(mutex_);
393 std::atomic<bool> stopped_boolean_ ABSL_GUARDED_BY(mutex_);
394 std::atomic<bool>* stopped_ ABSL_GUARDED_BY(mutex_);
434 double deterministic_limit);
448 template <
typename Parameters>
451 return absl::make_unique<NestedTimeLimit>(
474 double instruction_limit)
475 : safety_buffer_ns_(static_cast<int64_t>(kSafetyBufferSeconds * 1e9)),
476 running_max_(kHistorySize),
477 external_boolean_as_limit_(nullptr) {
478 ResetTimers(limit_in_seconds, deterministic_limit, instruction_limit);
481 inline void TimeLimit::ResetTimers(
double limit_in_seconds,
482 double deterministic_limit,
483 double instruction_limit) {
484 elapsed_deterministic_time_ = 0.0;
485 deterministic_limit_ = deterministic_limit;
486 instruction_limit_ = instruction_limit;
488 if (absl::GetFlag(FLAGS_time_limit_use_usertime)) {
490 limit_in_seconds_ = limit_in_seconds;
492 #ifdef HAS_PERF_SUBSYSTEM 493 if (absl::GetFlag(FLAGS_time_limit_use_instruction_count)) {
494 perf_subsystem_.CleanUp();
495 perf_subsystem_.AddEvent(GetInstructionRetiredEventName());
496 perf_subsystem_.StartCollecting();
498 #endif // HAS_PERF_SUBSYSTEM 499 start_ns_ = absl::GetCurrentTimeNanos();
500 last_ns_ = start_ns_;
501 limit_ns_ = limit_in_seconds >= 1e-9 * (
kint64max - start_ns_)
503 : static_cast<int64_t>(limit_in_seconds * 1e9) + start_ns_;
506 template <
typename Parameters>
510 std::numeric_limits<double>::infinity());
514 if (other ==
nullptr)
return;
518 std::numeric_limits<double>::infinity());
525 #ifdef HAS_PERF_SUBSYSTEM 526 if (absl::GetFlag(FLAGS_time_limit_use_instruction_count)) {
527 return perf_subsystem_.ReadCounters().GetScaledOrDie(
528 GetInstructionRetiredEventName());
530 #endif // HAS_PERF_SUBSYSTEM 535 if (external_boolean_as_limit_ !=
nullptr &&
536 external_boolean_as_limit_->load()) {
544 #ifdef HAS_PERF_SUBSYSTEM 548 #endif // HAS_PERF_SUBSYSTEM 550 const int64_t current_ns = absl::GetCurrentTimeNanos();
551 running_max_.
Add(
std::max(safety_buffer_ns_, current_ns - last_ns_));
552 last_ns_ = current_ns;
553 if (current_ns + running_max_.
GetCurrentMax() >= limit_ns_) {
554 if (absl::GetFlag(FLAGS_time_limit_use_usertime)) {
558 const double time_left_s = limit_in_seconds_ - user_timer_.
Get();
560 limit_ns_ = static_cast<int64_t>(time_left_s * 1e9) + last_ns_;
573 if (limit_ns_ ==
kint64max)
return std::numeric_limits<double>::infinity();
574 const int64_t delta_ns = limit_ns_ - absl::GetCurrentTimeNanos();
575 if (delta_ns < 0)
return 0.0;
576 if (absl::GetFlag(FLAGS_time_limit_use_usertime)) {
577 return std::max(limit_in_seconds_ - user_timer_.
Get(), 0.0);
579 return delta_ns * 1e-9;
589 #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...