diff --git a/eo/src/mpi/assignmentAlgorithm.h b/eo/src/mpi/assignmentAlgorithm.h new file mode 100644 index 00000000..bd635c23 --- /dev/null +++ b/eo/src/mpi/assignmentAlgorithm.h @@ -0,0 +1,49 @@ +# ifndef __ASSIGNMENT_ALGORITHM_H__ +# define __ASSIGNMENT_ALGORITHM_H__ + +struct AssignmentAlgorithm +{ + virtual int get( ) = 0; + virtual int size( ) = 0; + virtual void confirm( int wrkRank ) = 0; +}; + +struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm +{ + public: + DynamicAssignmentAlgorithm( int offset, int size ) + { + for( int i = 0; offset + i < size; ++i) + { + availableWrk.push_back( offset + i ); + } + } + + virtual int get( ) + { + int assignee = -1; + if (! availableWrk.empty() ) + { + assignee = availableWrk.back(); + availableWrk.pop_back(); + } + return assignee; + } + + int size() + { + return availableWrk.size(); + } + + void confirm( int rank ) + { + availableWrk.push_back( rank ); + } + + protected: + std::vector< int > availableWrk; +}; + + + +# endif // __ASSIGNMENT_ALGORITHM_H__ diff --git a/eo/src/mpi/eoParallelApply.h b/eo/src/mpi/eoParallelApply.h index 528d0cb2..80958e41 100644 --- a/eo/src/mpi/eoParallelApply.h +++ b/eo/src/mpi/eoParallelApply.h @@ -11,8 +11,8 @@ class ParallelApply : public MpiJob< EOT > { public: - ParallelApply( eoUF & _proc, std::vector& _pop ) : - MpiJob( _pop ), + ParallelApply( eoUF & _proc, std::vector& _pop, AssignmentAlgorithm & algo ) : + MpiJob( _pop, algo ), func( _proc ) { // empty diff --git a/eo/src/mpi/eompi.cpp b/eo/src/mpi/eompi.cpp index eff6bc39..6429a31c 100644 --- a/eo/src/mpi/eompi.cpp +++ b/eo/src/mpi/eompi.cpp @@ -1,4 +1,5 @@ # include "eompi.h" -MpiNode* MpiNodeStore::singleton; +// MpiNode* MpiNodeStore::singleton; +mpi::communicator MpiNode::_comm; diff --git a/eo/src/mpi/eompi.h b/eo/src/mpi/eompi.h index 9abcbb0f..3b04441d 100644 --- a/eo/src/mpi/eompi.h +++ b/eo/src/mpi/eompi.h @@ -7,6 +7,8 @@ # include namespace mpi = boost::mpi; +# include "assignmentAlgorithm.h" + # include using namespace std; // TODO TODOB comment! @@ -25,102 +27,22 @@ namespace EoMpi } } -class MpiNode; - -class MpiNodeStore +class MpiNode { public: - static void instance( MpiNode* _instance ) + static void init( int argc, char** argv ) { - singleton = _instance; + static mpi::environment env( argc, argv ); } - static MpiNode* instance() - { - return singleton; - } - - protected: - - static MpiNode* singleton; -}; - -class MpiNode -{ -protected: - mpi::environment& env; - mpi::communicator& _comm; - - int rank; - int size; - - int argc; - char** argv; - -public: - MpiNode( mpi::environment& _env, mpi::communicator& __comm ) : - env(_env), - _comm(__comm), - rank(__comm.rank()), - size(__comm.size()) - { - // empty - } - - virtual ~MpiNode() - { - // empty - } - - mpi::communicator& comm() + static mpi::communicator& comm() { return _comm; } -}; - -struct AssignmentAlgorithm -{ - virtual int get( ) = 0; - virtual void size( int s ) = 0; - virtual int size( ) = 0; - virtual void confirm( int wrkRank ) = 0; -}; - -struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm -{ - public: - virtual int get( ) - { - int assignee = -1; - if (! availableWrk.empty() ) - { - assignee = availableWrk.back(); - availableWrk.pop_back(); - } - return assignee; - } -; - void size( int s ) - { - for( int i = 1; i < s ; ++i ) - { - availableWrk.push_back( i ); - } - } - - int size() - { - return availableWrk.size(); - } - - void confirm( int rank ) - { - availableWrk.push_back( rank ); - } protected: - std::vector< int > availableWrk; + static mpi::communicator _comm; }; template< typename EOT > @@ -128,9 +50,10 @@ class MpiJob { public: - MpiJob( std::vector< EOT > & _data ) : + MpiJob( std::vector< EOT > & _data, AssignmentAlgorithm& algo ) : data( _data ), - comm( MpiNodeStore::instance()->comm() ) + comm( MpiNode::comm() ), + assignmentAlgo( algo ) { // empty } @@ -141,14 +64,14 @@ class MpiJob // worker virtual void processTask( ) = 0; - void master( AssignmentAlgorithm & assignmentAlgorithm ) + void master( ) { for( int i = 0, size = data.size(); i < size; ++i) { cout << "Beginning loop for i = " << i << endl; - int assignee = assignmentAlgorithm.get( ); + int assignee = assignmentAlgo.get( ); cout << "Assignee : " << assignee << endl; while( assignee <= 0 ) { @@ -157,8 +80,8 @@ class MpiJob int wrkRank = status.source(); cout << "Node " << wrkRank << " just terminated." << endl; handleResponse( wrkRank, assignedTasks[ wrkRank ] ); - assignmentAlgorithm.confirm( wrkRank ); - assignee = assignmentAlgorithm.get( ); + assignmentAlgo.confirm( wrkRank ); + assignee = assignmentAlgo.get( ); } cout << "Assignee found : " << assignee << endl; assignedTasks[ assignee ] = i; @@ -169,25 +92,25 @@ class MpiJob // frees all the idle workers int idle; vector idles; - while ( ( idle = assignmentAlgorithm.get( ) ) > 0 ) + while ( ( idle = assignmentAlgo.get( ) ) > 0 ) { comm.send( idle, EoMpi::Channel::Commands, EoMpi::Message::Finish ); idles.push_back( idle ); } for (int i = 0; i < idles.size(); ++i) { - assignmentAlgorithm.confirm( idles[i] ); + assignmentAlgo.confirm( idles[i] ); } // wait for all responses int wrkNb = comm.size() - 1; - while( assignmentAlgorithm.size() != wrkNb ) + while( assignmentAlgo.size() != wrkNb ) { mpi::status status = comm.probe( mpi::any_source, mpi::any_tag ); int wrkRank = status.source(); handleResponse( wrkRank, assignedTasks[ wrkRank ] ); comm.send( wrkRank, EoMpi::Channel::Commands, EoMpi::Message::Finish ); - assignmentAlgorithm.confirm( wrkRank ); + assignmentAlgo.confirm( wrkRank ); } } @@ -211,77 +134,44 @@ protected: std::vector & data; std::map< int /* worker rank */, int /* index in vector */> assignedTasks; - + AssignmentAlgorithm& assignmentAlgo; mpi::communicator& comm; }; -class MasterNode : public MpiNode -{ -public: - MasterNode( int _argc, char** _argv, - mpi::environment& _env, - mpi::communicator& _comm - ) : - MpiNode(_env, _comm ) - { - // empty - } - - void setAssignmentAlgorithm( AssignmentAlgorithm* assignmentAlgo ) - { - _assignmentAlgo = assignmentAlgo; - _assignmentAlgo->size( _comm.size() ); - } - - template< typename EOT > - void run( MpiJob< EOT > & job ) - { - job.master( *_assignmentAlgo ); - } - -protected: - AssignmentAlgorithm* _assignmentAlgo; -}; - -class WorkerNode : public MpiNode +template< class EOT > +class Role { public: - - WorkerNode( - int _argc, char** _argv, - mpi::environment& _env, - mpi::communicator& _comm ) : - MpiNode( _env, _comm ) + Role( MpiJob & job, bool master ) : + _job( job ), + _master( master ) { // empty } - template< typename EOT > - void run( MpiJob & job ) + bool master() { - job.worker( ); + return _master; } -}; -class MpiSingletonFactory -{ - public: - - static void init( int argc, char** argv ) - { - MpiNode* singleton; - //mpi::environment* env = new mpi::environment ( argc, argv ); - //mpi::communicator* world = new mpi::communicator; // TODO clean - static mpi::environment env( argc, argv ); - static mpi::communicator world; - if ( world.rank() == 0 ) + virtual void run( ) { - singleton = new MasterNode( argc, argv, env, world ); - } else - { - singleton = new WorkerNode( argc, argv, env, world ); + if( _master ) + { + _job.master( ); + } else + { + _job.worker( ); + } } - MpiNodeStore::instance( singleton ); - } + + virtual ~Role() + { + // empty + } + + protected: + bool _master; + MpiJob & _job; }; # endif // __EO_MPI_H__ diff --git a/eo/test/t-eoMpiParallelApply.cpp b/eo/test/t-eoMpiParallelApply.cpp index c20cc94f..ab559815 100644 --- a/eo/test/t-eoMpiParallelApply.cpp +++ b/eo/test/t-eoMpiParallelApply.cpp @@ -1,5 +1,6 @@ # include # include + # include # include @@ -15,9 +16,9 @@ struct plusOne : public eoUF< int&, void > int main(int argc, char** argv) { - DynamicAssignmentAlgorithm algo; cout << "Appel à init... " << endl; - MpiSingletonFactory::init( argc, argv ); + MpiNode::init( argc, argv ); + DynamicAssignmentAlgorithm algo( 1, MpiNode::comm().size() ); cout << "Création des données... " << endl; vector v; @@ -31,8 +32,19 @@ int main(int argc, char** argv) plusOne plusOneInstance; cout << "Création du job..." << endl; - ParallelApply job( plusOneInstance, v ); + ParallelApply job( plusOneInstance, v, algo ); + Role node( job, MpiNode::comm().rank() == 0 ); + node.run(); + if( node.master() ) + { + for(int i = 0; i < v.size(); ++i) + { + cout << v[i] << ' '; + } + cout << endl; + } + /* cout << "Création de l'instance..." << endl; MpiNode* instance = MpiNodeStore::instance(); if( dynamic_cast( instance ) != 0 ) @@ -54,6 +66,7 @@ int main(int argc, char** argv) { cout << "Nothing to be done;" << endl; } + */ return 0; }