parallel_solve.h
Go to the documentation of this file.
00001 // 
00002 // Copyright (c) 2010-2012, Benjamin Kaufmann
00003 // 
00004 // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ 
00005 // 
00006 // Clasp is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or
00009 // (at your option) any later version.
00010 // 
00011 // Clasp is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 // 
00016 // You should have received a copy of the GNU General Public License
00017 // along with Clasp; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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         // base interface
00096         virtual bool interrupted() const;
00097         virtual void resetSolve();
00098         virtual void enableInterrupts();
00099         // own interface
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         // Thread setup 
00122         struct EntryPoint;
00123         void   destroyThread(uint32 id);
00124         void   allocThread(uint32 id, Solver& s, const SolveParams& p); 
00125         void   joinThreads();
00126         // -------------------------------------------------------------------------------------------
00127         // Algorithm steps
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         // SHARED DATA
00144         SharedData*       shared_;       // Shared control data
00145         ParallelHandler** thread_;       // Thread-locl control data
00146         // READ ONLY
00147         Distribution      distribution_; // distribution options
00148         uint32            maxRestarts_;  // disable global restarts once reached 
00149         uint32            intGrace_ : 30;// grace period for clauses to integrate
00150         uint32            intTopo_  :  2;// integration topology
00151         uint32            intFlags_;     // bitset controlling clause integration
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;    // name of message
00160         double      time;   // only for action completed
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         // overridden methods
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         // own interface
00206         
00207         // TODO: make functions virtual once necessary 
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_;       // my message source
00262         Solver*            solver_;     // my solver
00263         const SolveParams* params_;     // my solving params
00264         Clasp::thread      thread_;     // active thread or empty for master
00265         RecBuffer          received_;   // received clauses not yet integrated
00266         ClauseDB           integrated_; // my integrated clauses
00267         size_type          recEnd_;     // where to put next received clause
00268         size_type          intEnd_;     // where to put next clause
00269         uint32             error_:30;   // error code or 0 if ok
00270         uint32             win_  : 1;   // 1 if thread was the first to terminate the search
00271         uint32             up_   : 1;   // 1 if next propagate should check for new lemmas/models
00272         uint32             act_  : 1;   // 1 if gp is active
00273         struct GP {
00274                 uint64 restart;  // don't give up before restart number of conflicts
00275                 uint32 modCount; // integration counter for synchronizing models
00276                 GpType type ;    // type of gp
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


clasp
Author(s): Benjamin Kaufmann
autogenerated on Thu Aug 27 2015 12:41:39