23 #include "absl/flags/flag.h"
24 #include "absl/strings/string_view.h"
25 #include "absl/synchronization/mutex.h"
26 #include "absl/time/clock.h"
27 #include "absl/time/time.h"
29 #if !defined(__PORTABLE_PLATFORM__)
43 int NextSubsolverToSchedule(
44 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
45 const std::vector<int64_t>& num_generated_tasks) {
47 for (
int i = 0; i < subsolvers.size(); ++i) {
48 if (subsolvers[i]->TaskIsAvailable()) {
49 if (best == -1 || num_generated_tasks[i] < num_generated_tasks[best]) {
54 if (best != -1)
VLOG(1) <<
"Scheduling " << subsolvers[best]->name();
58 void SynchronizeAll(
const std::vector<std::unique_ptr<SubSolver>>& subsolvers) {
59 for (
const auto& subsolver : subsolvers) subsolver->Synchronize();
64 void SequentialLoop(
const std::vector<std::unique_ptr<SubSolver>>& subsolvers) {
66 std::vector<int64_t> num_generated_tasks(subsolvers.size(), 0);
68 SynchronizeAll(subsolvers);
69 const int best = NextSubsolverToSchedule(subsolvers, num_generated_tasks);
70 if (best == -1)
break;
71 num_generated_tasks[best]++;
72 subsolvers[best]->GenerateTask(task_id++)();
76 #if defined(__PORTABLE_PLATFORM__)
81 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
87 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
int num_threads,
95 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
int num_threads,
97 CHECK_GT(num_threads, 0);
98 CHECK_GT(batch_size, 0);
99 if (batch_size == 1) {
104 std::vector<int64_t> num_generated_tasks(subsolvers.size(), 0);
105 std::vector<std::function<void()>> to_run;
106 to_run.reserve(batch_size);
108 SynchronizeAll(subsolvers);
113 for (
int t = 0; t < batch_size; ++t) {
114 const int best = NextSubsolverToSchedule(subsolvers, num_generated_tasks);
115 if (best == -1)
break;
116 num_generated_tasks[best]++;
117 to_run.push_back(subsolvers[best]->GenerateTask(task_id++));
119 if (to_run.empty())
break;
124 ThreadPool pool(
"DeterministicLoop", num_threads);
126 for (
auto& f : to_run) {
134 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
136 CHECK_GT(num_threads, 0);
137 if (num_threads == 1) {
144 absl::CondVar thread_available_condition;
145 int num_scheduled_and_not_done = 0;
147 ThreadPool pool(
"NonDeterministicLoop", num_threads);
154 std::vector<int64_t> num_generated_tasks(subsolvers.size(), 0);
156 bool all_done =
false;
158 absl::MutexLock mutex_lock(&mutex);
162 if (num_scheduled_and_not_done == 0) all_done =
true;
165 if (num_scheduled_and_not_done == num_threads) {
166 thread_available_condition.Wait(&mutex);
170 SynchronizeAll(subsolvers);
171 const int best = NextSubsolverToSchedule(subsolvers, num_generated_tasks);
179 absl::SleepFor(absl::Milliseconds(1));
184 num_generated_tasks[best]++;
186 absl::MutexLock mutex_lock(&mutex);
187 num_scheduled_and_not_done++;
189 std::function<void()> task = subsolvers[best]->GenerateTask(task_id++);
190 const std::string
name = subsolvers[best]->name();
191 pool.
Schedule([task, num_threads,
name, &mutex, &num_scheduled_and_not_done,
192 &thread_available_condition]() {
195 absl::MutexLock mutex_lock(&mutex);
197 num_scheduled_and_not_done--;
198 if (num_scheduled_and_not_done == num_threads - 1) {
199 thread_available_condition.SignalAll();
void Schedule(std::function< void()> closure)
void DeterministicLoop(const std::vector< std::unique_ptr< SubSolver >> &subsolvers, int num_threads, int batch_size)
void NonDeterministicLoop(const std::vector< std::unique_ptr< SubSolver >> &subsolvers, int num_threads)
void SequentialLoop(const std::vector< std::unique_ptr< SubSolver >> &subsolvers)
Collection of objects used to extend the Constraint Solver library.
#define VLOG(verboselevel)