distributed_engine_factory.hpp

00001 /*
00002 This file is part of GraphLab.
00003 
00004 GraphLab is free software: you can redistribute it and/or modify
00005 it under the terms of the GNU Lesser General Public License as 
00006 published by the Free Software Foundation, either version 3 of 
00007 the License, or (at your option) any later version.
00008 
00009 GraphLab is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public 
00015 License along with GraphLab.  If not, see <http://www.gnu.org/licenses/>.
00016 */
00017 
00018 #ifndef GRAPHLAB_DISTRIBUTED_ENGINE_FACTORY_HPP
00019 #define GRAPHLAB_DISTRIBUTED_ENGINE_FACTORY_HPP
00020 
00021 #include <string>
00022 #include <sstream>
00023 #include <graphlab/rpc/dc.hpp>
00024 
00025 // The graph is needed to build an engine
00026 #include <graphlab/distributed2/graph/distributed_graph.hpp>
00027 
00028 // The engines
00029 #include <graphlab/engine/iengine.hpp>
00030 #include <graphlab/distributed2/distributed_chromatic_engine.hpp>
00031 #include <graphlab/distributed2/distributed_locking_engine.hpp>
00032 #include <graphlab/engine/engine_options.hpp>
00033 
00034 
00035 
00036 // Scopes
00037 #include <graphlab/scope/general_scope_factory.hpp>
00038 
00039 
00040 // Schedulers
00041 #include <graphlab/distributed2/distributed_scheduler_list.hpp>
00042 
00043 #include <boost/preprocessor.hpp>
00044 
00045 
00046 namespace graphlab {
00047   
00048   
00049   /**
00050    *  helper for constructing graphlab engines.
00051    **/
00052   namespace distributed_engine_factory {
00053 
00054     template<typename Graph, typename Scheduler, typename ScopeFactory>
00055     iengine<Graph>* new_engine(distributed_control& dc,
00056                                const std::string& engine,
00057                                Graph& _graph,
00058                                size_t ncpus) {
00059       if(engine == "dist_locking") {
00060         typedef distributed_locking_engine<Graph, Scheduler> engine_type;
00061         return new engine_type(dc, _graph, ncpus);
00062       } if(engine == "dist_chromatic") {
00063         typedef distributed_chromatic_engine<Graph> engine_type;
00064         return new engine_type(dc, _graph, ncpus);
00065       } else {
00066         std::cout << "Invalid engine type: " << engine
00067                   << std::endl;
00068         return NULL;
00069       }
00070     } // end of new engine 
00071 
00072     
00073     template<typename Graph, typename Scheduler>
00074     iengine<Graph>* new_engine(distributed_control& dc,
00075                                const std::string& engine,
00076                                const std::string& scope_factory,
00077                                Graph& _graph,
00078                                size_t ncpus) {
00079       iengine<Graph>* ret = new_engine<Graph, Scheduler,
00080         general_scope_factory<Graph> >(dc, engine, _graph, ncpus);
00081       if(ret == NULL) { return NULL; }
00082       
00083       if(scope_factory == "unsync" || scope_factory == "vertex") {
00084         ret->set_default_scope(scope_range::VERTEX_CONSISTENCY);
00085       } else if(scope_factory == "locked" || scope_factory == "edge") {
00086         ret->set_default_scope(scope_range::EDGE_CONSISTENCY);
00087       } else if(scope_factory == "extlocked" || scope_factory == "full") {
00088         ret->set_default_scope(scope_range::FULL_CONSISTENCY);
00089       } else if(scope_factory == "null" || scope_factory == "none") {
00090         ret->set_default_scope(scope_range::NULL_CONSISTENCY);
00091       } else {
00092         std::cout << "Invalid scope type: " << scope_factory
00093                   << std::endl;
00094         return NULL;
00095       }
00096       
00097       if(scope_factory == "unsync" || scope_factory == "locked" ||
00098          scope_factory == "extlocked") {
00099         logstream(LOG_WARNING) << "The scope names \"unsync\", \"locked\""
00100           "and \"extlocked\" have been deprecated";
00101         logstream(LOG_WARNING) << "Please use the new names \"vertex\", "
00102           "\"edge\" and \"full\"" << std::endl;
00103       }
00104       return ret;
00105     }
00106 
00107   
00108 
00109 
00110 
00111     
00112 
00113 
00114     /**
00115      * Allocate an engine given engine options.
00116      */
00117     template<typename Graph>
00118     iengine<Graph>* new_engine(distributed_control& dc,
00119                                const engine_options& eopts,
00120                                Graph& _graph) {
00121       iengine<Graph>* eng = NULL;
00122 
00123 #define __GENERATE_NEW_ENGINE__(r_unused, data_unused, i,  elem)        \
00124       BOOST_PP_EXPR_IF(i, else)                                         \
00125         if (eopts.get_scheduler_type() == BOOST_PP_TUPLE_ELEM(3,0,elem)) { \
00126           eng = new_engine<Graph, BOOST_PP_TUPLE_ELEM(3,1,elem) <Graph> > \
00127             ( dc,                                                       \
00128               eopts.get_engine_type(),                                  \
00129               eopts.get_scope_type(),                                   \
00130               _graph,                                                   \
00131               eopts.get_ncpus() );                                      \
00132         }
00133       
00134       // generate the construction calls
00135       BOOST_PP_SEQ_FOR_EACH_I(__GENERATE_NEW_ENGINE__, _, __DISTRIBUTED_SCHEDULER_LIST__)
00136         /*
00137           if(scheduler == "fifo") {
00138           eng =  new_engine<Graph, fifo_scheduler<Graph> >(engine,
00139           scope_factory,
00140           _graph,
00141           ncpus);
00142           } else if ....*/
00143       else {
00144         std::cout << "Invalid scheduler type: " << eopts.get_scheduler_type()
00145                   << std::endl;
00146         return NULL;
00147       }
00148 
00149       if(eng != NULL) {
00150         // Should we merge instead?
00151         eng->set_scheduler_options( eopts.get_scheduler_options() );
00152       }
00153       return eng;
00154 #undef __GENERATE_NEW_ENGINE__ 
00155       
00156     } // end of new engine  
00157 
00158 
00159 
00160 
00161 
00162     /**
00163      * Deprecated but used by some older apps
00164      *
00165      * Allocate an engine given the strings for the engine type, scope
00166      * factory, and scheduler.
00167      *
00168      * \param engine  Type of engine to construct. {async, async_sim, synchronous}
00169      * \param scope    Type of scope to use.  {none, vertex, edge, full}
00170      * \param scheduler Type of scheduler to use synchronous, fifo, priority, sampling,
00171      *                 sweep, multiqueue_fifo, multiqueue_priority,
00172      *                 clustered_priority({metis, bfs, random}, verts. per part)
00173      *                 round_robin, chromatic}
00174      * 
00175      * Note that the caller is responsible for freeing the
00176      * corresponding engine
00177      * \anchor gl_new_engine
00178      */
00179     template<typename Graph>
00180     iengine<Graph>* new_engine(distributed_control &dc,
00181                                const std::string& engine_type,
00182                                const std::string& scheduler_type,
00183                                const std::string& scope_type,
00184                                Graph& _graph,
00185                                size_t ncpus) {
00186       engine_options eopts;
00187       eopts.set_engine_type(engine_type);
00188       eopts.set_scheduler_type(scheduler_type);
00189       eopts.set_scope_type(scope_type);
00190       eopts.set_ncpus(ncpus);
00191       return new_engine(dc, eopts, _graph);
00192     }
00193 
00194 
00195 
00196   }; // end of class engine factory
00197 }; // End of namespace graphl
00198 
00199 
00200 
00201 
00202 #endif
00203