Generated on for Gecode by doxygen 1.17.0
pbs.hpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.dev>
5 *
6 * Contributing authors:
7 * Mikael Zayenz Lagerkvist <lagerkvist@gecode.dev>
8 *
9 * Copyright:
10 * Christian Schulte, 2015
11 * Mikael Zayenz Lagerkvist, 2026
12 *
13 * This file is part of Gecode, the generic constraint
14 * development environment:
15 * http://www.gecode.dev
16 *
17 * Permission is hereby granted, free of charge, to any person obtaining
18 * a copy of this software and associated documentation files (the
19 * "Software"), to deal in the Software without restriction, including
20 * without limitation the rights to use, copy, modify, merge, publish,
21 * distribute, sublicense, and/or sell copies of the Software, and to
22 * permit persons to whom the Software is furnished to do so, subject to
23 * the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be
26 * included in all copies or substantial portions of the Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 *
36 */
37
38#include <algorithm>
39
40namespace Gecode { namespace Search { namespace Par {
41
42 template<class Collect>
43 forceinline
45 // A slave has not been submitted yet. This initial signal lets the
46 // first submission use the same consume-before-reuse handshake as all
47 // subsequent submissions.
48 done.signal();
49 }
50
51 template<class Collect>
52 forceinline void
56
57 template<class Collect>
58 forceinline void
60 done.wait();
61 }
62
63
64 forceinline
67 forceinline bool
69 solutions.push(s);
70 return true;
71 }
72 forceinline bool
74 (void) b;
75 return false;
76 }
77 forceinline bool
78 CollectAll::empty(void) const {
79 return solutions.empty();
80 }
81 forceinline Space*
83 return solutions.pop();
84 }
85 forceinline
87 while (!solutions.empty())
88 delete solutions.pop();
89 }
90
91
92 forceinline
94 : b(nullptr), reporter(nullptr) {}
95 forceinline bool
97 if (b != nullptr) {
98 b->constrain(*s);
99 if (b->status() == SS_FAILED) {
100 delete b;
101 } else {
102 delete s;
103 return false;
104 }
106 b = s;
108 return true;
110 forceinline bool
112 if (b != nullptr) {
113 b->constrain(s);
114 if (b->status() == SS_FAILED) {
115 delete b;
116 } else {
117 return false;
118 }
119 }
120 b = s.clone();
121 reporter = nullptr;
122 return true;
123 }
124 forceinline bool
125 CollectBest::empty(void) const {
126 return reporter == nullptr;
127 }
128 forceinline Space*
130 assert(!empty());
131 r = reporter;
132 reporter = nullptr;
133 return b->clone();
134 }
135 forceinline
137 delete b;
138 }
139
140
141 forceinline
143 : so(so0), tostop(nullptr) {}
144
145 forceinline void
146 PortfolioStop::share(std::atomic<bool>* ts) {
147 tostop = ts;
148 }
149
150
151 template<class Collect>
152 forceinline
154 : Support::Runnable(false), master(m), slave(s), stop(so) {}
155 template<class Collect>
156 forceinline Statistics
158 return slave->statistics();
159 }
160 template<class Collect>
161 forceinline bool
163 return slave->stopped();
164 }
165 template<class Collect>
166 forceinline Support::Terminator*
168 return const_cast<Completion*>(&completion);
169 }
170 template<class Collect>
171 forceinline void
173 completion.wait();
174 }
175 template<class Collect>
176 forceinline void
178 slave->constrain(b);
179 }
180 template<class Collect>
182 delete slave;
183 delete stop;
185
186
187
188 template<class Collect>
189 forceinline
190 PBS<Collect>::PBS(Engine** engines, Stop** stops, unsigned int n,
191 const Statistics& stat0)
192 : stat(stat0), slaves(heap.alloc<Slave<Collect>*>(n)),
193 n_slaves(n), n_active(n),
194 slave_stop(false), tostop(false), n_busy(0) {
195 // Initialize slaves
196 for (unsigned int i=0U; i<n_slaves; i++) {
197 slaves[i] = new Slave<Collect>(this,engines[i],stops[i]);
198 static_cast<PortfolioStop*>(stops[i])->share(&tostop);
200 }
202
203 template<class Collect>
204 forceinline bool
206 // If b is false the report should be repeated (solution was worse)
207 bool b = true;
208 m.acquire();
209 if (s != nullptr) {
210 b = solutions.add(s,slave);
211 if (b)
212 tostop.store(true, std::memory_order_release);
213 } else if (slave->stopped()) {
214 if (!tostop.load(std::memory_order_acquire))
215 slave_stop.store(true, std::memory_order_release);
216 } else {
217 // Move slave to inactive, as it has exhausted its engine
218 unsigned int i=0;
219 while (slaves[i] != slave)
220 i++;
221 assert(i < n_active);
222 assert(n_active > 0);
223 std::swap(slaves[i],slaves[--n_active]);
224 tostop.store(true, std::memory_order_release);
225 }
226 if (b) {
227 if (--n_busy == 0)
228 idle.signal();
229 }
230 m.release();
231 return b;
232 }
233
234 template<class Collect>
235 void
237 Space* s;
238 do {
239 s = slave->next();
240 } while (!master->report(this,s));
241 }
242
243 template<class Collect>
244 Space*
246 m.acquire();
247 if (solutions.empty()) {
248 // Clear all
249 tostop.store(false, std::memory_order_release);
250 slave_stop.store(false, std::memory_order_release);
251
252 // Invariant: all slaves are idle!
253 assert(n_busy == 0);
254 assert(!tostop.load(std::memory_order_acquire));
255
256 if (n_active > 0) {
257 // Run all active slaves
259 for (unsigned int i=0U; i<n_active; i++) {
260 // Consume the previous completion before reusing this slave. The
261 // initial signal handles the first submission.
262 slaves[i]->wait();
264 }
265 m.release();
266 // Wait for all slaves to become idle
267 idle.wait();
268 m.acquire();
269 }
270 }
271
272 // Invariant all slaves are idle!
273 assert(n_busy == 0);
274
275 Space* s;
276
277 // Process solutions
278 if (solutions.empty()) {
279 s = nullptr;
280 } else {
282 s = solutions.get(r);
283 if (Collect::best)
284 for (unsigned int i=0U; i<n_active; i++)
285 if (slaves[i] != r)
286 slaves[i]->constrain(*s);
287 }
288
289 m.release();
290 return s;
291 }
292
293 template<class Collect>
294 bool
296 return slave_stop.load(std::memory_order_acquire);
297 }
298
299 template<class Collect>
302 assert(n_busy == 0);
303 Statistics s(stat);
304 for (unsigned int i=0U; i<n_slaves; i++)
305 s += slaves[i]->statistics();
306 return s;
307 }
308
309 template<class Collect>
310 void
312 assert(n_busy == 0);
313 if (!Collect::best)
314 throw NoBest("PBS::constrain");
315 if (solutions.constrain(b)) {
316 // The solution is better
317 for (unsigned int i=0U; i<n_active; i++)
318 slaves[i]->constrain(b);
319 }
320 }
321
322 template<class Collect>
324 // A report can make n_busy zero before Slave::run and Thread::Run::exec
325 // have returned. Wait for the completion handshake before deleting the
326 // PBS-owned slaves.
327 for (unsigned int i=0U; i<n_slaves; i++)
328 slaves[i]->wait();
329 assert(n_busy == 0);
330 for (unsigned int i=0U; i<n_slaves; i++)
331 delete slaves[i];
333 }
334
335}}}
336
337// STATISTICS: search-par
Exception: Best solution search is not supported
Definition exception.hpp:60
Space * get(Slave< CollectAll > *&r)
Return solution reported by r.
Definition pbs.hpp:82
bool empty(void) const
Check whether there is any solution left.
Definition pbs.hpp:78
Support::DynamicQueue< Space *, Heap > solutions
Queue of solutions.
Definition pbs.hh:116
bool add(Space *s, Slave< CollectAll > *r)
Add a solution a reported by r and always return true.
Definition pbs.hpp:68
CollectAll(void)
Initialize.
Definition pbs.hpp:65
~CollectAll(void)
Destructor.
Definition pbs.hpp:86
bool constrain(const Space &b)
Dummy function.
Definition pbs.hpp:73
CollectBest(void)
Initialize.
Definition pbs.hpp:93
bool constrain(const Space &b)
Check whether b better and update accordingly.
Definition pbs.hpp:111
bool empty(void) const
Check whether there is any solution left.
Definition pbs.hpp:125
bool add(Space *s, Slave< CollectBest > *r)
Add a solution s by r and return whether is was better.
Definition pbs.hpp:96
Space * get(Slave< CollectBest > *&r)
Return solution reported by r (only if a better one was found).
Definition pbs.hpp:129
Slave< CollectBest > * reporter
Who has reported the best solution (nullptr if solution has already been reported).
Definition pbs.hh:140
~CollectBest(void)
Destructor.
Definition pbs.hpp:136
Space * b
Currently best solution.
Definition pbs.hh:138
Parallel depth-first search engine
Definition engine.hh:51
Engine(const Options &o)
Initialize with options o.
Definition engine.hpp:120
Parallel portfolio engine implementation.
Definition pbs.hh:160
virtual bool stopped(void) const
Check whether engine has been stopped.
Definition pbs.hpp:295
virtual ~PBS(void)
Destructor.
Definition pbs.hpp:323
Support::Event idle
Signal that number of busy slaves becomes zero.
Definition pbs.hh:182
bool report(Slave< Collect > *slave, Space *s)
Process report from slave, return false if solution was ignored.
Definition pbs.hpp:205
Collect solutions
Collect solutions in this.
Definition pbs.hh:176
friend class Slave< Collect >
Definition pbs.hh:161
Support::Mutex m
Mutex for synchronization.
Definition pbs.hh:178
Slave< Collect > ** slaves
Slave engines.
Definition pbs.hh:166
std::atomic< bool > tostop
Shared stop flag.
Definition pbs.hh:174
unsigned int n_active
Number of active slave engines.
Definition pbs.hh:170
unsigned int n_slaves
Number of slave engines.
Definition pbs.hh:168
Statistics stat
Master statistics.
Definition pbs.hh:164
PBS(Engine **s, Stop **so, unsigned int n, const Statistics &stat)
Initialize.
Definition pbs.hpp:190
virtual void constrain(const Space &b)
Constrain future solutions to be better than b.
Definition pbs.hpp:311
std::atomic< bool > slave_stop
Whether a slave has been stopped.
Definition pbs.hh:172
virtual Space * next(void)
Return next solution (nullptr, if none exists or search has been stopped).
Definition pbs.hpp:245
virtual Statistics statistics(void) const
Return statistics.
Definition pbs.hpp:301
unsigned int n_busy
Number of busy slaves.
Definition pbs.hh:180
Stop object used for controlling slaves in a portfolio.
Definition pbs.hh:47
void share(std::atomic< bool > *ts)
Set pointer to shared tostop variable.
Definition pbs.hpp:146
PortfolioStop(Stop *so)
Initialize.
Definition pbs.hpp:142
Completion event for the current run.
Definition pbs.hh:75
virtual void terminated(void)
Signal completion.
Definition pbs.hpp:53
void wait(void)
Wait for completion and consume the signal.
Definition pbs.hpp:59
Completion(void)
Initialize as completed.
Definition pbs.hpp:44
Support::Event done
The completion event.
Definition pbs.hh:78
Runnable slave of a portfolio master.
Definition pbs.hh:72
Engine * slave
The slave engine.
Definition pbs.hh:90
PBS< Collect > * master
The master engine.
Definition pbs.hh:88
void wait(void)
Wait for the slave to complete its current run.
Definition pbs.hpp:172
virtual Support::Terminator * terminator(void) const
Return the completion terminator.
Definition pbs.hpp:167
virtual void run(void)
Perform one run.
Definition pbs.hpp:236
bool stopped(void) const
Check whether slave has been stopped.
Definition pbs.hpp:162
virtual ~Slave(void)
Delete slave.
Definition pbs.hpp:181
Statistics statistics(void) const
Return statistics of slave.
Definition pbs.hpp:157
Slave(PBS< Collect > *m, Engine *s, Stop *so)
Initialize with master m, slave s, and its stop object so.
Definition pbs.hpp:153
Gecode::Search::Par::Slave::Completion completion
void constrain(const Space &b)
Constrain with better solution b.
Definition pbs.hpp:177
Stop * stop
Stop object.
Definition pbs.hh:92
Search engine statistics
Definition search.hh:151
Base-class for Stop-object.
Definition search.hh:804
Stop(void)
Default constructor.
Definition stop.hpp:45
Computation spaces.
Definition core.hpp:1775
Runnable(bool d=true)
Initialize, d defines whether object is deleted when terminated.
Definition thread.hpp:40
An interface for objects that can be called after a thread has terminated (after running the thread's...
Definition thread.hpp:168
static void run(Runnable *r)
Construct a new thread and run r.
Definition thread.hpp:177
Heap heap
The single global heap.
virtual void constrain(const Space &best)
Constrain function for best solution search.
Space * clone(void) const
Clone space.
Definition core.hpp:3312
SpaceStatus status(StatusStatistics &stat)
Query space status.
@ SS_FAILED
Space is failed
Definition core.hpp:1715
Search engines
Support algorithms and datastructures
Gecode toplevel namespace
void wait(Home home, FloatVar x, std::function< void(Space &home)> c)
Execute c when x becomes assigned.