From dfd653d95b36228fbda2679686a1d6498b0111b0 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 26 Jul 2012 14:45:31 +0200 Subject: [PATCH] MPI Multistart: moved MultiStart job into a standalone header, eoMultiStart.h. t-mpi-multistart.cpp becomes an example. --- eo/src/mpi/eoMultiStart.h | 314 +++++++++++++++++++++++++++++++ eo/test/mpi/t-mpi-multistart.cpp | 302 +---------------------------- 2 files changed, 315 insertions(+), 301 deletions(-) create mode 100644 eo/src/mpi/eoMultiStart.h diff --git a/eo/src/mpi/eoMultiStart.h b/eo/src/mpi/eoMultiStart.h new file mode 100644 index 000000000..456124f11 --- /dev/null +++ b/eo/src/mpi/eoMultiStart.h @@ -0,0 +1,314 @@ +# ifndef __EO_MULTISTART_H__ +# define __EO_MULTISTART_H__ + +# include +# include "eoMpi.h" + +namespace eo +{ + namespace mpi + { + template< class EOT > + struct MultiStartData + { + typedef eoUF< eoPop&, void> ResetAlgo; + + MultiStartData( bmpi::communicator& _comm, eoAlgo& _algo, int _masterRank, ResetAlgo & _resetAlgo ) + : + runs( 0 ), pop(), bests(), + comm( _comm ), algo( _algo ), masterRank( _masterRank ), resetAlgo( _resetAlgo ) + { + // empty + } + + // dynamic parameters + int runs; + eoPop< EOT > bests; + eoPop< EOT > pop; + + // static parameters + bmpi::communicator& comm; + eoAlgo& algo; + ResetAlgo& resetAlgo; + int masterRank; + }; + + template< class EOT > + class SendTaskMultiStart : public SendTaskFunction< MultiStartData< EOT > > + { + public: + using SendTaskFunction< MultiStartData< EOT > >::_data; + + void operator()( int wrkRank ) + { + --(_data->runs); + } + }; + + template< class EOT > + class HandleResponseMultiStart : public HandleResponseFunction< MultiStartData< EOT > > + { + public: + using HandleResponseFunction< MultiStartData< EOT > >::_data; + + void operator()( int wrkRank ) + { + EOT individual; + MultiStartData< EOT >& d = *_data; + d.comm.recv( wrkRank, 1, individual ); + d.bests.push_back( individual ); + } + }; + + template< class EOT > + class ProcessTaskMultiStart : public ProcessTaskFunction< MultiStartData< EOT > > + { + public: + using ProcessTaskFunction< MultiStartData >::_data; + + void operator()() + { + _data->resetAlgo( _data->pop ); + _data->algo( _data->pop ); + _data->comm.send( _data->masterRank, 1, _data->pop.best_element() ); + } + }; + + template< class EOT > + class IsFinishedMultiStart : public IsFinishedFunction< MultiStartData< EOT > > + { + public: + using IsFinishedFunction< MultiStartData< EOT > >::_data; + + bool operator()() + { + return _data->runs <= 0; + } + }; + + template< class EOT > + class MultiStartStore : public JobStore< MultiStartData< EOT > > + { + public: + + typedef typename MultiStartData::ResetAlgo ResetAlgo; + typedef eoUF< int, std::vector > GetSeeds; + + MultiStartStore( + eoAlgo & algo, + int masterRank, + ResetAlgo & resetAlgo, + GetSeeds & getSeeds + ) + : _data( eo::mpi::Node::comm(), algo, masterRank, resetAlgo ), + _getSeeds( getSeeds ), + _masterRank( masterRank ) + { + this->_iff = new IsFinishedMultiStart< EOT >; + this->_iff->needDelete(true); + this->_stf = new SendTaskMultiStart< EOT >; + this->_stf->needDelete(true); + this->_hrf = new HandleResponseMultiStart< EOT >; + this->_hrf->needDelete(true); + this->_ptf = new ProcessTaskMultiStart< EOT >; + this->_ptf->needDelete(true); + } + + void init( const std::vector& workers, int runs ) + { + _data.runs = runs; + + int nbWorkers = workers.size(); + std::vector< int > seeds = _getSeeds( nbWorkers ); + if( eo::mpi::Node::comm().rank() == _masterRank ) + { + if( seeds.size() < nbWorkers ) + { + // Random seeds + for( int i = seeds.size(); i < nbWorkers; ++i ) + { + seeds.push_back( eo::rng.rand() ); + } + } + + for( int i = 0 ; i < nbWorkers ; ++i ) + { + int wrkRank = workers[i]; + eo::mpi::Node::comm().send( wrkRank, 1, seeds[ i ] ); + } + } else + { + int seed; + eo::mpi::Node::comm().recv( _masterRank, 1, seed ); + eo::log << eo::debug << eo::mpi::Node::comm().rank() << "- Seed: " << seed << std::endl; + eo::rng.reseed( seed ); + } + } + + MultiStartData* data() + { + return &_data; + } + + private: + MultiStartData< EOT > _data; + GetSeeds & _getSeeds; + int _masterRank; + }; + + template + // No seeds! Use default generator + struct DummyGetSeeds : public MultiStartStore::GetSeeds + { + std::vector operator()( int n ) + { + return std::vector(); + } + }; + + template + // Multiple of a seed + struct MultiplesOfNumber : public MultiStartStore::GetSeeds + { + MultiplesOfNumber ( int n = 0 ) + { + while( n == 0 ) + { + n = eo::rng.rand(); + } + _seed = n; + _i = 0; + } + + std::vector operator()( int n ) + { + std::vector ret; + for( unsigned int i = 0; i < n; ++i ) + { + ret.push_back( (++_i) * _seed ); + } + return ret; + } + + private: + + unsigned int _seed; + unsigned int _i; + }; + + template + struct GetRandomSeeds : public MultiStartStore::GetSeeds + { + GetRandomSeeds( int seed ) + { + eo::rng.reseed( seed ); + } + + std::vector operator()( int n ) + { + std::vector ret; + for(int i = 0; i < n; ++i) + { + ret.push_back( eo::rng.rand() ); + } + return ret; + } + }; + + template + struct ReuseOriginalPopEA: public MultiStartStore::ResetAlgo + { + ReuseOriginalPopEA( + eoGenContinue & continuator, + const eoPop& originalPop, + eoEvalFunc& eval) : + _initial( continuator.totalGenerations() ), + _continuator( continuator ), + _originalPop( originalPop ), + _eval( eval ) + { + // empty + } + + void operator()( eoPop& pop ) + { + pop = _originalPop; + for(unsigned i = 0, size = pop.size(); i < size; ++i) + { + _eval( pop[i] ); + } + _continuator.totalGenerations( _initial ); + } + + private: + unsigned int _initial; + eoGenContinue & _continuator; + const eoPop& _originalPop; + eoEvalFunc& _eval; + }; + + template< class EOT > + struct ReuseSamePopEA : public MultiStartStore::ResetAlgo + { + ReuseSamePopEA( + eoGenContinue& continuator, + const eoPop& originalPop, + eoEvalFunc& eval + ) : + _continuator( continuator ), + _originalPop( originalPop ), + _firstTime( true ), + _initial( continuator.totalGenerations() ) + { + for( unsigned i = 0, size = originalPop.size(); + i < size; ++i ) + { + eval(_originalPop[i]); + } + } + + void operator()( eoPop& pop ) + { + if( _firstTime ) + { + pop = _originalPop; + _firstTime = false; + } + _continuator.totalGenerations( _initial ); + } + + protected: + + eoGenContinue& _continuator; + eoPop _originalPop; + bool _firstTime; + int _initial; + }; + + template< class EOT > + class MultiStart : public OneShotJob< MultiStartData< EOT > > + { + public: + + MultiStart( AssignmentAlgorithm & algo, + int masterRank, + MultiStartStore< EOT > & store, + // dynamic parameters + int runs, + const std::vector& seeds = std::vector() ) : + OneShotJob< MultiStartData< EOT > >( algo, masterRank, store ) + { + store.init( algo.idles(), runs ); + } + + eoPop& best_individuals() + { + return this->store.data()->bests; + } + }; + + } // namespace mpi + +} // namespace eo + +# endif // __EO_MULTISTART_H__ diff --git a/eo/test/mpi/t-mpi-multistart.cpp b/eo/test/mpi/t-mpi-multistart.cpp index 91db72e3a..a50c17a68 100644 --- a/eo/test/mpi/t-mpi-multistart.cpp +++ b/eo/test/mpi/t-mpi-multistart.cpp @@ -1,4 +1,4 @@ -# include +# include using namespace eo::mpi; #include @@ -76,306 +76,6 @@ double real_value(const Indi & _indi) } /************************** PARALLELIZATION JOB *******************************/ - -template< class EOT > -struct MultiStartData -{ - typedef eoUF< eoPop&, void> ResetAlgo; - - MultiStartData( mpi::communicator& _comm, eoAlgo& _algo, int _masterRank, ResetAlgo & _resetAlgo ) - : - runs( 0 ), pop(), bests(), - comm( _comm ), algo( _algo ), masterRank( _masterRank ), resetAlgo( _resetAlgo ) - { - // empty - } - - // dynamic parameters - int runs; - eoPop< EOT > bests; - eoPop< EOT > pop; - - // static parameters - mpi::communicator& comm; - eoAlgo& algo; - ResetAlgo& resetAlgo; - int masterRank; -}; - -template< class EOT > -class SendTaskMultiStart : public SendTaskFunction< MultiStartData< EOT > > -{ - public: - using SendTaskFunction< MultiStartData< EOT > >::_data; - - void operator()( int wrkRank ) - { - --(_data->runs); - } -}; - -template< class EOT > -class HandleResponseMultiStart : public HandleResponseFunction< MultiStartData< EOT > > -{ - public: - using HandleResponseFunction< MultiStartData< EOT > >::_data; - - void operator()( int wrkRank ) - { - EOT individual; - MultiStartData< EOT >& d = *_data; - d.comm.recv( wrkRank, 1, individual ); - d.bests.push_back( individual ); - } -}; - -template< class EOT > -class ProcessTaskMultiStart : public ProcessTaskFunction< MultiStartData< EOT > > -{ - public: - using ProcessTaskFunction< MultiStartData >::_data; - - void operator()() - { - _data->resetAlgo( _data->pop ); - _data->algo( _data->pop ); - _data->comm.send( _data->masterRank, 1, _data->pop.best_element() ); - } -}; - -template< class EOT > -class IsFinishedMultiStart : public IsFinishedFunction< MultiStartData< EOT > > -{ - public: - using IsFinishedFunction< MultiStartData< EOT > >::_data; - - bool operator()() - { - return _data->runs <= 0; - } -}; - -template< class EOT > -class MultiStartStore : public JobStore< MultiStartData< EOT > > -{ - public: - - typedef typename MultiStartData::ResetAlgo ResetAlgo; - typedef eoUF< int, std::vector > GetSeeds; - - MultiStartStore( - eoAlgo & algo, - int masterRank, - ResetAlgo & resetAlgo, - GetSeeds & getSeeds - ) - : _data( Node::comm(), algo, masterRank, resetAlgo ), - _getSeeds( getSeeds ), - _masterRank( masterRank ) - { - this->_iff = new IsFinishedMultiStart< EOT >; - this->_iff->needDelete(true); - this->_stf = new SendTaskMultiStart< EOT >; - this->_stf->needDelete(true); - this->_hrf = new HandleResponseMultiStart< EOT >; - this->_hrf->needDelete(true); - this->_ptf = new ProcessTaskMultiStart< EOT >; - this->_ptf->needDelete(true); - } - - void init( const std::vector& workers, int runs ) - { - _data.runs = runs; - - int nbWorkers = workers.size(); - std::vector< int > seeds = _getSeeds( nbWorkers ); - if( Node::comm().rank() == _masterRank ) - { - if( seeds.size() < nbWorkers ) - { - // Random seeds - for( int i = seeds.size(); i < nbWorkers; ++i ) - { - seeds.push_back( eo::rng.rand() ); - } - } - - for( int i = 0 ; i < nbWorkers ; ++i ) - { - int wrkRank = workers[i]; - Node::comm().send( wrkRank, 1, seeds[ i ] ); - } - } else - { - int seed; - Node::comm().recv( _masterRank, 1, seed ); - eo::log << eo::debug << Node::comm().rank() << "- Seed: " << seed << std::endl; - eo::rng.reseed( seed ); - } - } - - MultiStartData* data() - { - return &_data; - } - - private: - MultiStartData< EOT > _data; - GetSeeds & _getSeeds; - int _masterRank; -}; - -template< class EOT > -class MultiStart : public OneShotJob< MultiStartData< EOT > > -{ - public: - - MultiStart( AssignmentAlgorithm & algo, - int masterRank, - MultiStartStore< EOT > & store, - // dynamic parameters - int runs, - const std::vector& seeds = std::vector() ) : - OneShotJob< MultiStartData< EOT > >( algo, masterRank, store ) - { - store.init( algo.idles(), runs ); - } - - eoPop& best_individuals() - { - return this->store.data()->bests; - } -}; - -template -// No seeds! Use default generator -struct DummyGetSeeds : public MultiStartStore::GetSeeds -{ - std::vector operator()( int n ) - { - return std::vector(); - } -}; - -template -// Multiple of a seed -struct MultiplesOfNumber : public MultiStartStore::GetSeeds -{ - MultiplesOfNumber ( int n = 0 ) - { - while( n == 0 ) - { - n = eo::rng.rand(); - } - _seed = n; - _i = 0; - } - - std::vector operator()( int n ) - { - std::vector ret; - for( unsigned int i = 0; i < n; ++i ) - { - ret.push_back( (++_i) * _seed ); - } - return ret; - } - - private: - - unsigned int _seed; - unsigned int _i; -}; - -template -struct GetRandomSeeds : public MultiStartStore::GetSeeds -{ - GetRandomSeeds( int seed ) - { - eo::rng.reseed( seed ); - } - - std::vector operator()( int n ) - { - std::vector ret; - for(int i = 0; i < n; ++i) - { - ret.push_back( eo::rng.rand() ); - } - return ret; - } -}; - -template -struct ReuseOriginalPopEA: public MultiStartStore::ResetAlgo -{ - ReuseOriginalPopEA( - eoGenContinue & continuator, - const eoPop& originalPop, - eoEvalFunc& eval) : - _initial( continuator.totalGenerations() ), - _continuator( continuator ), - _originalPop( originalPop ), - _eval( eval ) - { - // empty - } - - void operator()( eoPop& pop ) - { - pop = _originalPop; - for(unsigned i = 0, size = pop.size(); i < size; ++i) - { - _eval( pop[i] ); - } - _continuator.totalGenerations( _initial ); - } - - private: - unsigned int _initial; - eoGenContinue & _continuator; - const eoPop& _originalPop; - eoEvalFunc& _eval; -}; - -template< class EOT > -struct ReuseSamePopEA : public MultiStartStore::ResetAlgo -{ - ReuseSamePopEA( - eoGenContinue& continuator, - const eoPop& originalPop, - eoEvalFunc& eval - ) : - _continuator( continuator ), - _originalPop( originalPop ), - _firstTime( true ), - _initial( continuator.totalGenerations() ) - { - for( unsigned i = 0, size = originalPop.size(); - i < size; ++i ) - { - eval(_originalPop[i]); - } - } - - void operator()( eoPop& pop ) - { - if( _firstTime ) - { - pop = _originalPop; - _firstTime = false; - } - _continuator.totalGenerations( _initial ); - } - - protected: - - eoGenContinue& _continuator; - eoPop _originalPop; - bool _firstTime; - int _initial; -}; - int main(int argc, char **argv) { Node::init( argc, argv );