00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef CLASP_PARALLEL_SOLVE_H_INCLUDED
00021 #define CLASP_PARALLEL_SOLVE_H_INCLUDED
00022
00023 #ifdef _MSC_VER
00024 #pragma once
00025 #endif
00026
00027 #if WITH_THREADS
00028
00029 #include <clasp/solve_algorithms.h>
00030 #include <clasp/constraint.h>
00031 #include <clasp/shared_context.h>
00032 #include <clasp/util/thread.h>
00033 #include <clasp/util/multi_queue.h>
00034 #include <clasp/solver_types.h>
00035
00041 namespace Clasp { namespace mt {
00042
00043 class ParallelHandler;
00044 class ParallelSolve;
00045
00046 struct ParallelSolveOptions : BasicSolveOptions {
00047 typedef Distributor::Policy Distribution;
00048 ParallelSolveOptions() {}
00049 struct Algorithm {
00050 enum SearchMode { mode_split = 0, mode_compete = 1 };
00051 Algorithm() : threads(1), mode(mode_compete) {}
00052 uint32 threads;
00053 SearchMode mode;
00054 };
00055 struct Integration {
00056 static const uint32 GRACE_MAX = (1u<<28)-1;
00057 Integration() : grace(1024), filter(filter_gp), topo(topo_all) {}
00058 enum Filter { filter_no = 0, filter_gp = 1, filter_sat = 2, filter_heuristic = 3 };
00059 enum Topology { topo_all = 0, topo_ring = 1, topo_cube = 2, topo_cubex = 3 };
00060 uint32 grace : 28;
00061 uint32 filter: 2;
00062 uint32 topo : 2;
00063 };
00064 struct GRestarts {
00065 GRestarts():maxR(0) {}
00066 uint32 maxR;
00067 ScheduleStrategy sched;
00068 };
00069 Integration integrate;
00070 Distribution distribute;
00071 GRestarts restarts;
00072 Algorithm algorithm;
00073
00074 SolveAlgorithm* createSolveObject() const;
00076 static uint32 recommendedSolvers() { return Clasp::thread::hardware_concurrency(); }
00078 static uint32 supportedSolvers() { return 64; }
00079 uint32 numSolver() const { return algorithm.threads; }
00080 bool defaultPortfolio() const { return algorithm.mode == Algorithm::mode_compete; }
00081 };
00082
00084
00091 class ParallelSolve : public SolveAlgorithm {
00092 public:
00093 explicit ParallelSolve(Enumerator* e, const ParallelSolveOptions& opts);
00094 ~ParallelSolve();
00095
00096 virtual bool interrupted() const;
00097 virtual void resetSolve();
00098 virtual void enableInterrupts();
00099
00101 uint32 numThreads() const;
00102 bool integrateUseHeuristic() const { return test_bit(intFlags_, 31); }
00103 uint32 integrateGrace() const { return intGrace_; }
00104 uint32 integrateFlags() const { return intFlags_; }
00105 uint64 hasErrors() const;
00107 void requestRestart();
00108 bool handleMessages(Solver& s);
00109 bool integrateModels(Solver& s, uint32& mCount);
00110 void pushWork(LitVec* gp);
00111 bool commitModel(Solver& s);
00112 bool commitUnsat(Solver& s);
00113 enum GpType { gp_none = 0, gp_split = 1, gp_fixed = 2 };
00114 private:
00115 ParallelSolve(const ParallelSolve&);
00116 ParallelSolve& operator=(const ParallelSolve&);
00117 typedef SingleOwnerPtr<const LitVec> PathPtr;
00118 enum ErrorCode { error_none = 0, error_oom = 1, error_runtime = 2, error_other = 4 };
00119 enum { masterId = 0 };
00120
00121
00122 struct EntryPoint;
00123 void destroyThread(uint32 id);
00124 void allocThread(uint32 id, Solver& s, const SolveParams& p);
00125 void joinThreads();
00126
00127
00128 void setIntegrate(uint32 grace, uint8 filter);
00129 void setRestarts(uint32 maxR, const ScheduleStrategy& rs);
00130 bool beginSolve(SharedContext& ctx);
00131 bool doSolve(SharedContext& ctx, const LitVec& assume);
00132 bool doInterrupt();
00133 void solveParallel(uint32 id);
00134 void initQueue();
00135 bool requestWork(Solver& s, PathPtr& out);
00136 void terminate(Solver& s, bool complete);
00137 bool waitOnSync(Solver& s);
00138 void exception(uint32 id, PathPtr& path, ErrorCode e, const char* what);
00139 void reportProgress(const Event& ev) const;
00140
00141 typedef ParallelSolveOptions::Distribution Distribution;
00142 struct SharedData;
00143
00144 SharedData* shared_;
00145 ParallelHandler** thread_;
00146
00147 Distribution distribution_;
00148 uint32 maxRestarts_;
00149 uint32 intGrace_ : 30;
00150 uint32 intTopo_ : 2;
00151 uint32 intFlags_;
00152 GpType initialGp_;
00153 };
00154
00155 struct MessageEvent : SolveEvent<MessageEvent> {
00156 enum Action { sent, received, completed };
00157 MessageEvent(const Solver& s, const char* message, Action a, double t = 0.0)
00158 : SolveEvent<MessageEvent>(s, verbosity_high), msg(message), time(t) { op = (uint32)a; }
00159 const char* msg;
00160 double time;
00161 };
00163
00167 class ParallelHandler : public MessageHandler {
00168 public:
00169 typedef ParallelSolve::GpType GpType;
00170
00172
00177 explicit ParallelHandler(ParallelSolve& ctrl, Solver& s, const SolveParams& p);
00178 ~ParallelHandler();
00180 bool attach(SharedContext& ctx);
00182 void detach(SharedContext& ctx, bool fastExit);
00183
00184 void setError(int e) { error_ = e; }
00185 int error() const { return (int)error_; }
00186 void setWinner() { win_ = 1; }
00187 bool winner() const { return win_ != 0; }
00188 void setThread(Clasp::thread& x) { assert(!joinable()); x.swap(thread_); assert(joinable()); }
00189
00191 bool joinable() const { return thread_.joinable(); }
00193 int join() { if (joinable()) { thread_.join(); } return error(); }
00194
00195
00196
00198 bool propagateFixpoint(Solver& s, PostPropagator*);
00199 bool handleMessages() { return ctrl_->handleMessages(solver()); }
00200 void reset() { up_ = 1; }
00201 bool simplify(Solver& s, bool re);
00203 bool isModel(Solver& s);
00204
00205
00206
00207
00208
00210 bool disjointPath() const { return gp_.type == ParallelSolve::gp_split; }
00212 bool hasPath() const { return gp_.type != ParallelSolve::gp_none; }
00213 void setGpType(GpType t) { gp_.type = t; }
00214
00216
00221 ValueRep solveGP(BasicSolve& solve, GpType type, uint64 restart);
00222
00230
00232
00235 void handleTerminateMessage();
00236
00238
00242 void handleSplitMessage();
00243
00245
00248 bool handleRestartMessage();
00249
00250 Solver& solver() { return *solver_; }
00251 const SolveParams& params() const{ return *params_; }
00253 private:
00254 void add(ClauseHead* h);
00255 void clearDB(Solver* s);
00256 bool integrate(Solver& s);
00257 typedef LitVec::size_type size_type;
00258 typedef PodVector<Constraint*>::type ClauseDB;
00259 typedef SharedLiterals** RecBuffer;
00260 enum { RECEIVE_BUFFER_SIZE = 32 };
00261 ParallelSolve* ctrl_;
00262 Solver* solver_;
00263 const SolveParams* params_;
00264 Clasp::thread thread_;
00265 RecBuffer received_;
00266 ClauseDB integrated_;
00267 size_type recEnd_;
00268 size_type intEnd_;
00269 uint32 error_:30;
00270 uint32 win_ : 1;
00271 uint32 up_ : 1;
00272 uint32 act_ : 1;
00273 struct GP {
00274 uint64 restart;
00275 uint32 modCount;
00276 GpType type ;
00277 void reset(uint64 r = UINT64_MAX, GpType t = ParallelSolve::gp_none) {
00278 restart = r;
00279 modCount= 0;
00280 type = t;
00281 }
00282 } gp_;
00283 };
00284
00285 class GlobalQueue : public Distributor {
00286 public:
00287 explicit GlobalQueue(const Policy& p, uint32 maxShare, uint32 topo);
00288 ~GlobalQueue();
00289 uint32 receive(const Solver& in, SharedLiterals** out, uint32 maxOut);
00290 void publish(const Solver& source, SharedLiterals* n);
00291 private:
00292 void release();
00293 struct DistPair {
00294 DistPair(uint32 sId = UINT32_MAX, SharedLiterals* x = 0) : sender(sId), lits(x) {}
00295 uint32 sender;
00296 SharedLiterals* lits;
00297 };
00298 class Queue : public MultiQueue<DistPair> {
00299 public:
00300 typedef MultiQueue<DistPair> base_type;
00301 using base_type::publish;
00302 Queue(uint32 m) : base_type(m) {}
00303 };
00304 struct ThreadInfo {
00305 Queue::ThreadId id;
00306 uint64 peerMask;
00307 char pad[64 - sizeof(Queue::ThreadId)];
00308 };
00309 Queue::ThreadId& getThreadId(uint32 sId) const { return threadId_[sId].id; }
00310 uint64 getPeerMask(uint32 sId) const { return threadId_[sId].peerMask; }
00311 uint64 populatePeerMask(uint32 topo, uint32 maxT, uint32 id) const;
00312 uint64 populateFromCube(uint32 maxT, uint32 id, bool ext) const;
00313 Queue* queue_;
00314 ThreadInfo* threadId_;
00315 };
00316
00317 } }
00318 #endif
00319
00320 #endif