20 #if !defined(__PORTABLE_PLATFORM__)
21 #include "absl/synchronization/mutex.h"
22 #include "absl/time/clock.h"
35 int NextSubsolverToSchedule(
36 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
37 const std::vector<int64_t>& num_generated_tasks) {
39 for (
int i = 0; i < subsolvers.size(); ++i) {
40 if (subsolvers[i]->TaskIsAvailable()) {
41 if (best == -1 || num_generated_tasks[i] < num_generated_tasks[best]) {
46 if (best != -1)
VLOG(1) <<
"Scheduling " << subsolvers[best]->name();
50 void SynchronizeAll(
const std::vector<std::unique_ptr<SubSolver>>& subsolvers) {
51 for (
const auto& subsolver : subsolvers) subsolver->Synchronize();
56 void SequentialLoop(
const std::vector<std::unique_ptr<SubSolver>>& subsolvers) {
58 std::vector<int64_t> num_generated_tasks(subsolvers.size(), 0);
60 SynchronizeAll(subsolvers);
61 const int best = NextSubsolverToSchedule(subsolvers, num_generated_tasks);
62 if (best == -1)
break;
63 num_generated_tasks[best]++;
64 subsolvers[best]->GenerateTask(task_id++)();
68 #if defined(__PORTABLE_PLATFORM__)
73 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
79 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
int num_threads,
87 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
int num_threads,
91 if (batch_size == 1) {
96 std::vector<int64_t> num_generated_tasks(subsolvers.size(), 0);
98 SynchronizeAll(subsolvers);
103 ThreadPool pool(
"DeterministicLoop", num_threads);
106 int num_in_batch = 0;
107 for (
int t = 0; t < batch_size; ++t) {
108 const int best = NextSubsolverToSchedule(subsolvers, num_generated_tasks);
109 if (best == -1)
break;
111 num_generated_tasks[best]++;
112 pool.
Schedule(subsolvers[best]->GenerateTask(task_id++));
114 if (num_in_batch == 0)
break;
119 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
122 if (num_threads == 1) {
129 absl::CondVar thread_available_condition;
130 int num_scheduled_and_not_done = 0;
132 ThreadPool pool(
"NonDeterministicLoop", num_threads);
139 std::vector<int64_t> num_generated_tasks(subsolvers.size(), 0);
141 bool all_done =
false;
143 absl::MutexLock mutex_lock(&mutex);
147 if (num_scheduled_and_not_done == 0) all_done =
true;
150 if (num_scheduled_and_not_done == num_threads) {
151 thread_available_condition.Wait(&mutex);
155 SynchronizeAll(subsolvers);
156 const int best = NextSubsolverToSchedule(subsolvers, num_generated_tasks);
164 absl::SleepFor(absl::Milliseconds(1));
169 num_generated_tasks[best]++;
171 absl::MutexLock mutex_lock(&mutex);
172 num_scheduled_and_not_done++;
174 std::function<void()> task = subsolvers[best]->GenerateTask(task_id++);
175 const std::string
name = subsolvers[best]->name();
176 pool.
Schedule([task, num_threads,
name, &mutex, &num_scheduled_and_not_done,
177 &thread_available_condition]() {
180 absl::MutexLock mutex_lock(&mutex);
182 num_scheduled_and_not_done--;
183 if (num_scheduled_and_not_done == num_threads - 1) {
184 thread_available_condition.SignalAll();
#define CHECK_GT(val1, val2)
#define VLOG(verboselevel)
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.