pbs.hpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 namespace Gecode { namespace Search { namespace Meta { namespace Parallel {
00039
00040
00041 forceinline
00042 CollectAll::CollectAll(void)
00043 : solutions(heap) {}
00044 forceinline bool
00045 CollectAll::add(Space* s, Slave<CollectAll>*) {
00046 solutions.push(s);
00047 return true;
00048 }
00049 forceinline bool
00050 CollectAll::constrain(const Space& b) {
00051 (void) b;
00052 return false;
00053 }
00054 forceinline bool
00055 CollectAll::empty(void) const {
00056 return solutions.empty();
00057 }
00058 forceinline Space*
00059 CollectAll::get(Slave<CollectAll>*&) {
00060 return solutions.pop();
00061 }
00062 forceinline
00063 CollectAll::~CollectAll(void) {
00064 }
00065
00066
00067 forceinline
00068 CollectBest::CollectBest(void)
00069 : b(NULL), reporter(NULL) {}
00070 forceinline bool
00071 CollectBest::add(Space* s, Slave<CollectBest>* r) {
00072 if (b != NULL) {
00073 b->constrain(*s);
00074 if (b->status() == SS_FAILED) {
00075 delete b;
00076 } else {
00077 delete s;
00078 return false;
00079 }
00080 }
00081 b = s;
00082 reporter = r;
00083 return true;
00084 }
00085 forceinline bool
00086 CollectBest::constrain(const Space& s) {
00087 if (b != NULL) {
00088 b->constrain(s);
00089 if (b->status() == SS_FAILED) {
00090 delete b;
00091 } else {
00092 return false;
00093 }
00094 }
00095 b = s.clone(false);
00096 reporter = NULL;
00097 return true;
00098 }
00099 forceinline bool
00100 CollectBest::empty(void) const {
00101 return reporter == NULL;
00102 }
00103 forceinline Space*
00104 CollectBest::get(Slave<CollectBest>*& r) {
00105 assert(!empty());
00106 r = reporter;
00107 reporter = NULL;
00108 return b->clone(false);
00109 }
00110 forceinline
00111 CollectBest::~CollectBest(void) {
00112 delete b;
00113 }
00114
00115
00116 forceinline
00117 PortfolioStop::PortfolioStop(Stop* so0)
00118 : so(so0), tostop(NULL) {}
00119
00120 forceinline void
00121 PortfolioStop::share(volatile bool* ts) {
00122 tostop = ts;
00123 }
00124
00125
00126 template<class Collect>
00127 forceinline
00128 Slave<Collect>::Slave(PBS<Collect>* m, Engine* s, Stop* so)
00129 : Support::Runnable(false), master(m), slave(s), stop(so) {}
00130 template<class Collect>
00131 forceinline Statistics
00132 Slave<Collect>::statistics(void) const {
00133 return slave->statistics();
00134 }
00135 template<class Collect>
00136 forceinline bool
00137 Slave<Collect>::stopped(void) const {
00138 return slave->stopped();
00139 }
00140 template<class Collect>
00141 forceinline void
00142 Slave<Collect>::constrain(const Space& b) {
00143 slave->constrain(b);
00144 }
00145 template<class Collect>
00146 Slave<Collect>::~Slave(void) {
00147 delete slave;
00148 delete stop;
00149 }
00150
00151
00152
00153 template<class Collect>
00154 forceinline
00155 PBS<Collect>::PBS(Engine** engines, Stop** stops, unsigned int n,
00156 const Statistics& stat0)
00157 : stat(stat0), slaves(heap.alloc<Slave<Collect>*>(n)), n_slaves(n),
00158 slave_stop(false), tostop(false), n_busy(0) {
00159
00160 for (unsigned int i=n_slaves; i--; ) {
00161 slaves[i] = new Slave<Collect>(this,engines[i],stops[i]);
00162 static_cast<PortfolioStop*>(stops[i])->share(&tostop);
00163 }
00164 }
00165
00166 template<class Collect>
00167 forceinline bool
00168 PBS<Collect>::report(Slave<Collect>* slave, Space* s) {
00169
00170 bool b = true;
00171 m.acquire();
00172 if (s != NULL) {
00173 b = solutions.add(s,slave);
00174 if (b)
00175 tostop = true;
00176 } else if (slave->stopped()) {
00177 if (!tostop)
00178 slave_stop = true;
00179 } else {
00180
00181 stat += slave->statistics();
00182
00183 slave->todelete(true);
00184 unsigned int i=0;
00185 while (slaves[i] != slave)
00186 i++;
00187 assert(i < n_slaves);
00188 slaves[i] = slaves[--n_slaves];
00189 }
00190 if (b) {
00191 if (--n_busy == 0)
00192 idle.signal();
00193 }
00194 m.release();
00195 return b;
00196 }
00197
00198 template<class Collect>
00199 void
00200 Slave<Collect>::run(void) {
00201 Space* s;
00202 do {
00203 s = slave->next();
00204 } while (!master->report(this,s));
00205 }
00206
00207 template<class Collect>
00208 Space*
00209 PBS<Collect>::next(void) {
00210 m.acquire();
00211 if (solutions.empty()) {
00212
00213 tostop = false;
00214 slave_stop = false;
00215
00216
00217 assert(n_busy == 0);
00218 assert(!tostop);
00219
00220 if (n_slaves > 0) {
00221
00222 n_busy = n_slaves;
00223 for (unsigned int i=n_slaves; i--; )
00224 Support::Thread::run(slaves[i]);
00225 m.release();
00226
00227 idle.wait();
00228 m.acquire();
00229 }
00230 }
00231
00232
00233 assert(n_busy == 0);
00234
00235 Space* s;
00236
00237
00238 if (solutions.empty()) {
00239 s = NULL;
00240 } else {
00241 Slave<Collect>* r;
00242 s = solutions.get(r);
00243 if (Collect::best)
00244 for (unsigned int i=n_slaves; i--; )
00245 if (slaves[i] != r)
00246 slaves[i]->constrain(*s);
00247 }
00248
00249 m.release();
00250 return s;
00251 }
00252
00253 template<class Collect>
00254 bool
00255 PBS<Collect>::stopped(void) const {
00256 return slave_stop;
00257 }
00258
00259 template<class Collect>
00260 Statistics
00261 PBS<Collect>::statistics(void) const {
00262 Statistics s(stat);
00263 for (unsigned int i=n_slaves; i--; )
00264 s += slaves[i]->statistics();
00265 return s;
00266 }
00267
00268 template<class Collect>
00269 void
00270 PBS<Collect>::constrain(const Space& b) {
00271 if (!Collect::best)
00272 throw NoBest("PBS::constrain");
00273 if (solutions.constrain(b)) {
00274
00275 for (unsigned int i=n_slaves; i--; )
00276 slaves[i]->constrain(b);
00277 }
00278 }
00279
00280 template<class Collect>
00281 PBS<Collect>::~PBS(void) {
00282 for (unsigned int i=n_slaves; i--; )
00283 delete slaves[i];
00284
00285 heap.rfree(slaves);
00286 }
00287
00288 }}}}
00289
00290