22#include "absl/flags/flag.h"
23#include "absl/strings/string_view.h"
24#include "absl/synchronization/mutex.h"
25#include "absl/time/clock.h"
26#include "absl/time/time.h"
28#if !defined(__PORTABLE_PLATFORM__)
42int NextSubsolverToSchedule(
43 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
44 const std::vector<int64_t>& num_generated_tasks) {
46 for (
int i = 0; i < subsolvers.size(); ++i) {
47 if (subsolvers[i]->TaskIsAvailable()) {
48 if (best == -1 || num_generated_tasks[i] < num_generated_tasks[best]) {
53 if (best != -1)
VLOG(1) <<
"Scheduling " << subsolvers[best]->name();
57void SynchronizeAll(
const std::vector<std::unique_ptr<SubSolver>>& subsolvers) {
58 for (
const auto& subsolver : subsolvers) subsolver->Synchronize();
63void SequentialLoop(
const std::vector<std::unique_ptr<SubSolver>>& subsolvers) {
65 std::vector<int64_t> num_generated_tasks(subsolvers.size(), 0);
67 SynchronizeAll(subsolvers);
68 const int best = NextSubsolverToSchedule(subsolvers, num_generated_tasks);
69 if (best == -1)
break;
70 num_generated_tasks[best]++;
71 subsolvers[best]->GenerateTask(task_id++)();
75#if defined(__PORTABLE_PLATFORM__)
80 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
86 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
int num_threads,
94 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
int num_threads,
98 if (batch_size == 1) {
103 std::vector<int64_t> num_generated_tasks(subsolvers.size(), 0);
105 SynchronizeAll(subsolvers);
110 ThreadPool pool(
"DeterministicLoop", num_threads);
113 int num_in_batch = 0;
114 for (
int t = 0; t < batch_size; ++t) {
115 const int best = NextSubsolverToSchedule(subsolvers, num_generated_tasks);
116 if (best == -1)
break;
118 num_generated_tasks[best]++;
119 pool.
Schedule(subsolvers[best]->GenerateTask(task_id++));
121 if (num_in_batch == 0)
break;
126 const std::vector<std::unique_ptr<SubSolver>>& subsolvers,
129 if (num_threads == 1) {
136 absl::CondVar thread_available_condition;
137 int num_scheduled_and_not_done = 0;
139 ThreadPool pool(
"NonDeterministicLoop", num_threads);
146 std::vector<int64_t> num_generated_tasks(subsolvers.size(), 0);
148 bool all_done =
false;
150 absl::MutexLock mutex_lock(&mutex);
154 if (num_scheduled_and_not_done == 0) all_done =
true;
157 if (num_scheduled_and_not_done == num_threads) {
158 thread_available_condition.Wait(&mutex);
162 SynchronizeAll(subsolvers);
163 const int best = NextSubsolverToSchedule(subsolvers, num_generated_tasks);
171 absl::SleepFor(absl::Milliseconds(1));
176 num_generated_tasks[best]++;
178 absl::MutexLock mutex_lock(&mutex);
179 num_scheduled_and_not_done++;
181 std::function<void()> task = subsolvers[best]->GenerateTask(task_id++);
182 const std::string
name = subsolvers[best]->name();
183 pool.
Schedule([task, num_threads,
name, &mutex, &num_scheduled_and_not_done,
184 &thread_available_condition]() {
187 absl::MutexLock mutex_lock(&mutex);
189 num_scheduled_and_not_done--;
190 if (num_scheduled_and_not_done == num_threads - 1) {
191 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 SequentialLoop(const std::vector< std::unique_ptr< SubSolver > > &subsolvers)
void NonDeterministicLoop(const std::vector< std::unique_ptr< SubSolver > > &subsolvers, int num_threads)
Collection of objects used to extend the Constraint Solver library.