diff --git a/eo/test/mpi/t-mpi-common.h b/eo/test/mpi/t-mpi-common.h new file mode 100644 index 00000000..4217af28 --- /dev/null +++ b/eo/test/mpi/t-mpi-common.h @@ -0,0 +1,43 @@ +# ifndef __T_MPI_COMMON_H__ +# define __T_MPI_COMMON_H__ + +#include + +template< class T > +struct SerializableBase : public eoserial::Persistent +{ + public: + + operator T&() + { + return _value; + } + + SerializableBase() : _value() + { + // empty + } + + SerializableBase( T base ) : _value( base ) + { + // empty + } + + void unpack( const eoserial::Object* obj ) + { + eoserial::unpack( *obj, "value", _value ); + } + + eoserial::Object* pack(void) const + { + eoserial::Object* obj = new eoserial::Object; + obj->add("value", eoserial::make( _value ) ); + return obj; + } + + private: + T _value; +}; + + +# endif // __T_MPI_COMMON_H__ diff --git a/eo/test/mpi/t-mpi-eval.cpp b/eo/test/mpi/t-mpi-eval.cpp index dc00a548..4187c4e6 100644 --- a/eo/test/mpi/t-mpi-eval.cpp +++ b/eo/test/mpi/t-mpi-eval.cpp @@ -34,7 +34,7 @@ Authors: #include -#include +// #include #include using namespace std; @@ -55,6 +55,14 @@ class eoRealSerializable : public eoReal< eoMinimizingFitness >, public eoserial eoserial::makeArray< vector, eoserial::MakeAlgorithm > ( *this ) ); + + bool invalidFitness = invalid(); + obj->add("invalid", eoserial::make( invalidFitness ) ); + if( !invalidFitness ) + { + double fitnessVal = fitness(); + obj->add("fitness", eoserial::make( fitnessVal ) ); + } return obj; } @@ -62,14 +70,23 @@ class eoRealSerializable : public eoReal< eoMinimizingFitness >, public eoserial { eoserial::unpackArray< vector, eoserial::Array::UnpackAlgorithm > ( *obj, "array", *this ); + + bool invalidFitness; + eoserial::unpack( *obj, "invalid", invalidFitness ); + if( invalidFitness ) { + invalidate(); + } else { + double fitnessVal; + eoserial::unpack( *obj, "fitness", fitnessVal ); + fitness( fitnessVal ); + } } + /* // Gives access to boost serialization friend class boost::serialization::access; - /** - * Serializes the decomposition in a boost archive (useful for boost::mpi) - */ + template void save( Archive & ar, const unsigned int version ) const { @@ -81,9 +98,7 @@ class eoRealSerializable : public eoReal< eoMinimizingFitness >, public eoserial (void) version; // avoid compilation warning } - /** - * Deserializes the decomposition from a boost archive (useful for boost:mpi) - */ + template void load( Archive & ar, const unsigned int version ) { @@ -98,6 +113,7 @@ class eoRealSerializable : public eoReal< eoMinimizingFitness >, public eoserial // Indicates that boost save and load operations are not the same. BOOST_SERIALIZATION_SPLIT_MEMBER() + */ }; diff --git a/eo/test/mpi/t-mpi-multipleRoles.cpp b/eo/test/mpi/t-mpi-multipleRoles.cpp index 36d588b8..db4b1bb6 100644 --- a/eo/test/mpi/t-mpi-multipleRoles.cpp +++ b/eo/test/mpi/t-mpi-multipleRoles.cpp @@ -41,7 +41,9 @@ Authors: # include # include -# include +# include "t-mpi-common.h" + +// # include # include @@ -50,10 +52,30 @@ using namespace std; using namespace eo::mpi; -// The real job to execute, for the subworkers: add one to each element of a table. -struct SubWork: public eoUF< int&, void > +template< class T > +struct SerializableVector : public std::vector, public eoserial::Persistent { - void operator() ( int & x ) + public: + + void unpack( const eoserial::Object* obj ) + { + this->clear(); + eoserial::Array* vector = static_cast( obj->find("vector")->second ); + vector->deserialize< std::vector, eoserial::Array::UnpackObjectAlgorithm >( *this ); + } + + eoserial::Object* pack( void ) const + { + eoserial::Object* obj = new eoserial::Object; + obj->add("vector", eoserial::makeArray< std::vector, eoserial::SerializablePushAlgorithm >( *this ) ); + return obj; + } +}; + +// The real job to execute, for the subworkers: add one to each element of a table. +struct SubWork: public eoUF< SerializableBase&, void > +{ + void operator() ( SerializableBase & x ) { cout << "Subwork phase." << endl; ++x; @@ -62,7 +84,7 @@ struct SubWork: public eoUF< int&, void > // Function called by both subworkers and delegates. // v is the vector to process, rank is the MPI rank of the sub master -void subtask( vector& v, int rank ) +void subtask( vector< SerializableBase >& v, int rank ) { // Attach workers according to nodes. // Submaster with rank 1 will have ranks 3 and 5 as subworkers. @@ -74,9 +96,9 @@ void subtask( vector& v, int rank ) SubWork sw; // Launch the job! - ParallelApplyStore store( sw, rank ); + ParallelApplyStore< SerializableBase > store( sw, rank ); store.data( v ); - ParallelApply job( algo, rank, store ); + ParallelApply< SerializableBase > job( algo, rank, store ); job.run(); EmptyJob stop( algo, rank ); } @@ -85,9 +107,9 @@ void subtask( vector& v, int rank ) // each result by two). // Note that this work receives a vector of integers as an entry, while subworkers task's operator receives a simple // integer. -struct Work: public eoUF< vector&, void > +struct Work: public eoUF< SerializableVector< SerializableBase >&, void > { - void operator() ( vector& v ) + void operator() ( SerializableVector< SerializableBase >& v ) { cout << "Work phase..." << endl; subtask( v, Node::comm().rank() ); @@ -103,10 +125,10 @@ int main(int argc, char** argv) // eo::log << eo::setlevel( eo::debug ); Node::init( argc, argv ); if( Node::comm().size() != 7 ) { - throw std::runtime_error("World size should be 7."); + // throw std::runtime_error("World size should be 7."); } - vector v; + SerializableVector< SerializableBase > v; v.push_back(1); v.push_back(3); @@ -116,7 +138,7 @@ int main(int argc, char** argv) // As submasters' operator receives a vector as an input, and ParallelApply takes a vector of // operator's input as an input, we have to deal with a vector of vector of integers for the master task. - vector< vector > metaV; + vector< SerializableVector< SerializableBase > > metaV; // Here, we send twice the same vector. We could also have splitted the first vector into two vectors, one // containing the beginning and another one containing the end. metaV.push_back( v ); @@ -132,9 +154,9 @@ int main(int argc, char** argv) { Work w; DynamicAssignmentAlgorithm algo( 1, 2 ); - ParallelApplyStore< vector > store( w, 0 ); + ParallelApplyStore< SerializableVector< SerializableBase > > store( w, 0 ); store.data( metaV ); - ParallelApply< vector > job( algo, 0, store ); + ParallelApply< SerializableVector< SerializableBase > > job( algo, 0, store ); job.run(); if( job.isMaster() ) { diff --git a/eo/test/mpi/t-mpi-parallelApply.cpp b/eo/test/mpi/t-mpi-parallelApply.cpp index 7cefa203..df90f0f5 100644 --- a/eo/test/mpi/t-mpi-parallelApply.cpp +++ b/eo/test/mpi/t-mpi-parallelApply.cpp @@ -40,6 +40,8 @@ Authors: # include # include +# include "t-mpi-common.h" + # include # include @@ -50,9 +52,9 @@ using namespace eo::mpi; /* * The function to be called on each element of the table: just increment the value. */ -struct plusOne : public eoUF< int&, void > +struct plusOne : public eoUF< SerializableBase&, void > { - void operator() ( int & x ) + void operator() ( SerializableBase & x ) { ++x; } @@ -79,7 +81,7 @@ int main(int argc, char** argv) // Initializes a vector with random values. srand( time(0) ); - vector v; + vector< SerializableBase > v; for( int i = 0; i < 1000; ++i ) { v.push_back( rand() ); @@ -90,7 +92,7 @@ int main(int argc, char** argv) // incremented and we can compare the returned value of each element to the value of each element in originalV + // offset. If the two values are different, there has been a problem. int offset = 0; - vector originalV = v; + vector< SerializableBase > originalV = v; // Instanciates the functor to apply on each element plusOne plusOneInstance; @@ -166,11 +168,11 @@ int main(int argc, char** argv) for( unsigned int i = 0; i < tests.size(); ++i ) { // Instanciates a store with the functor, the master rank and size of packet (see ParallelApplyStore doc). - ParallelApplyStore< int > store( plusOneInstance, eo::mpi::DEFAULT_MASTER, 3 ); + ParallelApplyStore< SerializableBase > store( plusOneInstance, eo::mpi::DEFAULT_MASTER, 3 ); // Updates the contained data store.data( v ); // Creates the job with the assignment algorithm, the master rank and the store - ParallelApply< int > job( *(tests[i].assign), eo::mpi::DEFAULT_MASTER, store ); + ParallelApply< SerializableBase > job( *(tests[i].assign), eo::mpi::DEFAULT_MASTER, store ); // Only master writes information if( job.isMaster() ) diff --git a/eo/test/mpi/t-mpi-wrapper.cpp b/eo/test/mpi/t-mpi-wrapper.cpp index 97d4b04a..7da45ad4 100644 --- a/eo/test/mpi/t-mpi-wrapper.cpp +++ b/eo/test/mpi/t-mpi-wrapper.cpp @@ -33,6 +33,8 @@ Authors: # include # include +# include "t-mpi-common.h" + # include # include @@ -41,9 +43,9 @@ using namespace std; using namespace eo::mpi; // Job functor. -struct plusOne : public eoUF< int&, void > +struct plusOne : public eoUF< SerializableBase&, void > { - void operator() ( int & x ) + void operator() ( SerializableBase& x ) { ++x; } @@ -83,28 +85,28 @@ int main(int argc, char** argv) Node::init( argc, argv ); srand( time(0) ); - vector v; + vector< SerializableBase > v; for( int i = 0; i < 1000; ++i ) { v.push_back( rand() ); } int offset = 0; - vector originalV = v; + vector< SerializableBase > originalV = v; plusOne plusOneInstance; StaticAssignmentAlgorithm assign( v.size() ); - ParallelApplyStore< int > store( plusOneInstance, eo::mpi::DEFAULT_MASTER, 1 ); + ParallelApplyStore< SerializableBase > store( plusOneInstance, eo::mpi::DEFAULT_MASTER, 1 ); store.data( v ); // This is the only thing which changes: we wrap the IsFinished function. // According to RAII, we'll delete the invokated wrapper at the end of the main ; the store won't delete it // automatically. - IsFinishedParallelApply* wrapper = new ShowWrappedResult; - store.wrapIsFinished( wrapper ); + ShowWrappedResult< SerializableBase > wrapper; + store.wrapIsFinished( &wrapper ); - ParallelApply job( assign, eo::mpi::DEFAULT_MASTER, store ); + ParallelApply< SerializableBase > job( assign, eo::mpi::DEFAULT_MASTER, store ); // Equivalent to: // Job< ParallelApplyData > job( assign, 0, store ); job.run(); @@ -125,8 +127,6 @@ int main(int argc, char** argv) cout << endl; } - delete wrapper; - return 0; }