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_ENGINE_FACTORY_HPP
00019 #define GRAPHLAB_ENGINE_FACTORY_HPP
00020 
00021 #include <string>
00022 #include <sstream>
00023 // The graph is needed to build an engine
00024 #include <graphlab/graph/graph.hpp>
00025 
00026 // The engines
00027 #include <graphlab/engine/iengine.hpp>
00028 #include <graphlab/engine/asynchronous_engine.hpp>
00029 #include <graphlab/engine/engine_options.hpp>
00030 
00031 
00032 
00033 // Scopes
00034 #include <graphlab/scope/general_scope_factory.hpp>
00035 
00036 
00037 // Schedulers
00038 #include <graphlab/schedulers/scheduler_list.hpp>
00039 
00040 #include <boost/preprocessor.hpp>
00041 
00042 
00043 namespace graphlab {
00044   
00045   
00046   /**
00047    *  helper for constructing graphlab engines.
00048    **/
00049   namespace engine_factory {
00050 
00051     template<typename Graph, typename Scheduler, typename ScopeFactory>
00052     iengine<Graph>* new_engine(const std::string& engine,
00053                                Graph& _graph,
00054                                size_t ncpus) {
00055       if(engine == "async") {
00056         typedef asynchronous_engine<Graph, Scheduler, ScopeFactory> engine_type;
00057         return new engine_type(_graph, ncpus, engine_type::THREADED);
00058       } if(engine == "async_sim") {
00059         typedef asynchronous_engine<Graph, Scheduler, ScopeFactory> engine_type;
00060         return new engine_type(_graph, ncpus, engine_type::SIMULATED);
00061       } else {
00062         std::cout << "Invalid engine type: " << engine
00063                   << std::endl;
00064         return NULL;
00065       }
00066     } // end of new engine 
00067 
00068     
00069     template<typename Graph, typename Scheduler>
00070     iengine<Graph>* new_engine(const std::string& engine,
00071                                const std::string& scope_factory,
00072                                Graph& _graph,
00073                                size_t ncpus) {
00074       iengine<Graph>* ret = new_engine<Graph, Scheduler,
00075         general_scope_factory<Graph> >(engine,
00076                                        _graph,
00077                                        ncpus);
00078       if(ret == NULL) { return NULL; }
00079       
00080       if(scope_factory == "unsync" || scope_factory == "vertex") {
00081         ret->set_default_scope(scope_range::VERTEX_CONSISTENCY);
00082       } else if(scope_factory == "locked" || scope_factory == "edge") {
00083         ret->set_default_scope(scope_range::EDGE_CONSISTENCY);
00084       } else if(scope_factory == "extlocked" || scope_factory == "full") {
00085         ret->set_default_scope(scope_range::FULL_CONSISTENCY);
00086       } else if(scope_factory == "null" || scope_factory == "none") {
00087         ret->set_default_scope(scope_range::NULL_CONSISTENCY);
00088       } else {
00089         std::cout << "Invalid scope type: " << scope_factory
00090                   << std::endl;
00091         return NULL;
00092       }
00093       
00094       if(scope_factory == "unsync" || scope_factory == "locked" ||
00095          scope_factory == "extlocked") {
00096         logstream(LOG_WARNING) << "The scope names \"unsync\", \"locked\""
00097           "and \"extlocked\" have been deprecated";
00098         logstream(LOG_WARNING) << "Please use the new names \"vertex\", "
00099           "\"edge\" and \"full\"" << std::endl;
00100       }
00101       return ret;
00102     }
00103 
00104   
00105 
00106 
00107 
00108     
00109 
00110 
00111     /**
00112      * Allocate an engine given engine options.
00113      */
00114     template<typename Graph>
00115     iengine<Graph>* new_engine(const engine_options& eopts,
00116                                Graph& _graph) {
00117       iengine<Graph>* eng = NULL;
00118 
00119 #define __GENERATE_NEW_ENGINE__(r_unused, data_unused, i,  elem)        \
00120       BOOST_PP_EXPR_IF(i, else)                                         \
00121         if (eopts.get_scheduler_type() == BOOST_PP_TUPLE_ELEM(3,0,elem)) { \
00122           eng = new_engine<Graph, BOOST_PP_TUPLE_ELEM(3,1,elem) <Graph> > \
00123             ( eopts.get_engine_type(),                                  \
00124               eopts.get_scope_type(),                                   \
00125               _graph,                                                   \
00126               eopts.get_ncpus() );                                      \
00127         }
00128       
00129       // generate the construction calls
00130       BOOST_PP_SEQ_FOR_EACH_I(__GENERATE_NEW_ENGINE__, _, __SCHEDULER_LIST__)
00131         /*
00132           if(scheduler == "fifo") {
00133           eng =  new_engine<Graph, fifo_scheduler<Graph> >(engine,
00134           scope_factory,
00135           _graph,
00136           ncpus);
00137           } else if ....*/
00138       else {
00139         std::cout << "Invalid scheduler type: " << eopts.get_scheduler_type()
00140                   << std::endl;
00141         return NULL;
00142       }
00143 
00144       if(eng != NULL) {
00145         // Should we merge instead?
00146         eng->set_scheduler_options( eopts.get_scheduler_options() );
00147       }
00148       return eng;
00149 #undef __GENERATE_NEW_ENGINE__ 
00150       
00151     } // end of new engine  
00152 
00153 
00154 
00155 
00156 
00157     /**
00158      * Deprecated but used by some older apps
00159      *
00160      * Allocate an engine given the strings for the engine type, scope
00161      * factory, and scheduler.
00162      *
00163      * \param engine  Type of engine to construct. {async, async_sim, synchronous}
00164      * \param scope    Type of scope to use.  {none, vertex, edge, full}
00165      * \param scheduler Type of scheduler to use synchronous, fifo, priority, sampling,
00166      *                 sweep, multiqueue_fifo, multiqueue_priority,
00167      *                 clustered_priority({metis, bfs, random}, verts. per part)
00168      *                 round_robin, chromatic}
00169      * 
00170      * Note that the caller is responsible for freeing the
00171      * corresponding engine
00172      * \anchor gl_new_engine
00173      */
00174     template<typename Graph>
00175     iengine<Graph>* new_engine(const std::string& engine_type,
00176                                const std::string& scheduler_type,
00177                                const std::string& scope_type,
00178                                Graph& _graph,
00179                                size_t ncpus) {
00180       engine_options eopts;
00181       eopts.set_engine_type(engine_type);
00182       eopts.set_scheduler_type(scheduler_type);
00183       eopts.set_scope_type(scope_type);
00184       eopts.set_ncpus(ncpus);
00185       return new_engine(eopts, _graph);
00186     }
00187 
00188 
00189 
00190   }; // end of class engine factory
00191 }; // End of namespace graphl
00192 
00193 
00194 
00195 
00196 #endif
00197