manual merge on eoPop.h
This commit is contained in:
commit
36f30db313
29 changed files with 1946 additions and 332 deletions
|
|
@ -15,7 +15,6 @@ INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/contrib/MGE)
|
|||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
IF(WITH_MPI)
|
||||
INCLUDE_DIRECTORIES(${BOOST_DIR}/include)
|
||||
INCLUDE_DIRECTORIES(${MPI_DIR}/include)
|
||||
ENDIF()
|
||||
|
||||
|
|
@ -26,7 +25,6 @@ ENDIF()
|
|||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
|
||||
IF(WITH_MPI)
|
||||
LINK_DIRECTORIES(${BOOST_DIR}/lib)
|
||||
LINK_DIRECTORIES(${MPI_DIR}/lib)
|
||||
SET(CMAKE_CXX_COMPILER "${MPI_DIR}/bin/mpicxx")
|
||||
ENDIF()
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@
|
|||
|
||||
MESSAGE("EO SOURCE DIR: ${EO_SOURCE_DIR}")
|
||||
MESSAGE("OMPI: ${MPI_DIR}")
|
||||
MESSAGE("BOOST: ${BOOST_DIR}")
|
||||
|
||||
INCLUDE_DIRECTORIES(${MPI_DIR}/include)
|
||||
INCLUDE_DIRECTORIES(${BOOST_DIR}/include)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
|
|
@ -23,7 +21,6 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
|||
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
LINK_DIRECTORIES(${MPI_DIR}/lib)
|
||||
LINK_DIRECTORIES(${BOOST_DIR}/lib)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets and link the librairies
|
||||
|
|
@ -34,6 +31,7 @@ SET (TEST_LIST
|
|||
t-mpi-wrapper
|
||||
t-mpi-multipleRoles
|
||||
t-mpi-eval
|
||||
t-mpi-multistart
|
||||
)
|
||||
|
||||
FOREACH (test ${TEST_LIST})
|
||||
|
|
@ -47,7 +45,7 @@ IF(ENABLE_CMAKE_TESTING)
|
|||
FOREACH (test ${TEST_LIST})
|
||||
ADD_EXECUTABLE(${test} ${T_${test}_SOURCES})
|
||||
ADD_TEST(${test} ${test})
|
||||
TARGET_LINK_LIBRARIES(${test} boost_mpi boost_serialization eoutils eompi eoserial eo)
|
||||
TARGET_LINK_LIBRARIES(${test} eoutils eompi eoserial eo)
|
||||
INSTALL(TARGETS ${test} RUNTIME DESTINATION share/eo/test COMPONENT test)
|
||||
ENDFOREACH (test)
|
||||
ENDIF()
|
||||
|
|
|
|||
51
eo/test/mpi/t-mpi-common.h
Normal file
51
eo/test/mpi/t-mpi-common.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# ifndef __T_MPI_COMMON_H__
|
||||
# define __T_MPI_COMMON_H__
|
||||
|
||||
#include <serial/eoSerial.h>
|
||||
|
||||
/**
|
||||
* @file t-mpi-common.h
|
||||
*
|
||||
* This file shows an example of serialization of a primitive type, so as to be used in a parallel algorithm.
|
||||
* It is fully compatible with the basic type, by implementing conversion operator and constructor based on type.
|
||||
* It can contain any simple type which can be written in a std::ostream.
|
||||
*/
|
||||
|
||||
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__
|
||||
|
|
@ -34,8 +34,6 @@ Authors:
|
|||
|
||||
#include <mpi/eoMpi.h>
|
||||
|
||||
#include <boost/mpi.hpp>
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -55,50 +53,33 @@ class eoRealSerializable : public eoReal< eoMinimizingFitness >, public eoserial
|
|||
eoserial::makeArray< vector<double>, 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;
|
||||
}
|
||||
|
||||
void unpack( const eoserial::Object* obj )
|
||||
{
|
||||
this->clear();
|
||||
eoserial::unpackArray< vector<double>, eoserial::Array::UnpackAlgorithm >
|
||||
( *obj, "array", *this );
|
||||
|
||||
bool invalidFitness;
|
||||
eoserial::unpack( *obj, "invalid", invalidFitness );
|
||||
if( invalidFitness ) {
|
||||
invalidate();
|
||||
} else {
|
||||
double fitnessVal;
|
||||
eoserial::unpack<double>( *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 <class Archive>
|
||||
void save( Archive & ar, const unsigned int version ) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printOn( ss );
|
||||
std::string asStr = ss.str();
|
||||
ar & asStr;
|
||||
|
||||
(void) version; // avoid compilation warning
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the decomposition from a boost archive (useful for boost:mpi)
|
||||
*/
|
||||
template <class Archive>
|
||||
void load( Archive & ar, const unsigned int version )
|
||||
{
|
||||
std::string asStr;
|
||||
ar & asStr;
|
||||
std::stringstream ss;
|
||||
ss << asStr;
|
||||
readFrom( ss );
|
||||
|
||||
(void) version; // avoid compilation warning
|
||||
}
|
||||
|
||||
// Indicates that boost save and load operations are not the same.
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
|
||||
};
|
||||
|
||||
typedef eoRealSerializable EOT;
|
||||
|
|
@ -196,14 +177,12 @@ int main(int ac, char** av)
|
|||
|
||||
eo::log << "Size of population : " << popSize << std::endl;
|
||||
|
||||
/*
|
||||
eo::mpi::ParallelApplyStore< EOT > store( eval, eo::mpi::DEFAULT_MASTER );
|
||||
store.wrapHandleResponse( new CatBestAnswers );
|
||||
|
||||
eoParallelPopLoopEval< EOT > popEval( assign, eo::mpi::DEFAULT_MASTER, &store );
|
||||
*/
|
||||
|
||||
eoParallelPopLoopEval< EOT > popEval( assign, eo::mpi::DEFAULT_MASTER, eval, 5 );
|
||||
//eoParallelPopLoopEval< EOT > popEval( assign, eo::mpi::DEFAULT_MASTER, eval, 5 );
|
||||
|
||||
eo::log << eo::quiet << "Before first evaluation." << std::endl;
|
||||
popEval( pop, pop );
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ Authors:
|
|||
# include <mpi/eoParallelApply.h>
|
||||
# include <mpi/eoTerminateJob.h>
|
||||
|
||||
# include <boost/serialization/vector.hpp>
|
||||
# include "t-mpi-common.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
|
|
@ -50,10 +50,37 @@ 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 >
|
||||
/*
|
||||
* This class allows the user to easily serialize a vector of elements which implement eoserial::Persistent too.
|
||||
*
|
||||
* T is the type of the contained element, which must implement eoserial::Persistent too.
|
||||
*
|
||||
* Here, it contains SerializableBase<int>, which is a serializable integer that can be used as an integer.
|
||||
*/
|
||||
template< class T >
|
||||
struct SerializableVector : public std::vector<T>, public eoserial::Persistent
|
||||
{
|
||||
void operator() ( int & x )
|
||||
public:
|
||||
|
||||
void unpack( const eoserial::Object* obj )
|
||||
{
|
||||
this->clear();
|
||||
eoserial::Array* vector = static_cast<eoserial::Array*>( obj->find("vector")->second );
|
||||
vector->deserialize< std::vector<T>, eoserial::Array::UnpackObjectAlgorithm >( *this );
|
||||
}
|
||||
|
||||
eoserial::Object* pack( void ) const
|
||||
{
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
obj->add("vector", eoserial::makeArray< std::vector<T>, 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<int>&, void >
|
||||
{
|
||||
void operator() ( SerializableBase<int> & x )
|
||||
{
|
||||
cout << "Subwork phase." << endl;
|
||||
++x;
|
||||
|
|
@ -62,7 +89,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<int>& v, int rank )
|
||||
void subtask( vector< SerializableBase<int> >& v, int rank )
|
||||
{
|
||||
// Attach workers according to nodes.
|
||||
// Submaster with rank 1 will have ranks 3 and 5 as subworkers.
|
||||
|
|
@ -74,9 +101,9 @@ void subtask( vector<int>& v, int rank )
|
|||
SubWork sw;
|
||||
|
||||
// Launch the job!
|
||||
ParallelApplyStore<int> store( sw, rank );
|
||||
ParallelApplyStore< SerializableBase<int> > store( sw, rank );
|
||||
store.data( v );
|
||||
ParallelApply<int> job( algo, rank, store );
|
||||
ParallelApply< SerializableBase<int> > job( algo, rank, store );
|
||||
job.run();
|
||||
EmptyJob stop( algo, rank );
|
||||
}
|
||||
|
|
@ -85,9 +112,9 @@ void subtask( vector<int>& 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<int>&, void >
|
||||
struct Work: public eoUF< SerializableVector< SerializableBase<int> >&, void >
|
||||
{
|
||||
void operator() ( vector<int>& v )
|
||||
void operator() ( SerializableVector< SerializableBase<int> >& v )
|
||||
{
|
||||
cout << "Work phase..." << endl;
|
||||
subtask( v, Node::comm().rank() );
|
||||
|
|
@ -106,7 +133,7 @@ int main(int argc, char** argv)
|
|||
throw std::runtime_error("World size should be 7.");
|
||||
}
|
||||
|
||||
vector<int> v;
|
||||
SerializableVector< SerializableBase<int> > v;
|
||||
|
||||
v.push_back(1);
|
||||
v.push_back(3);
|
||||
|
|
@ -116,7 +143,7 @@ int main(int argc, char** argv)
|
|||
|
||||
// As submasters' operator receives a vector<int> 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<int> > metaV;
|
||||
vector< SerializableVector< SerializableBase<int> > > 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 +159,9 @@ int main(int argc, char** argv)
|
|||
{
|
||||
Work w;
|
||||
DynamicAssignmentAlgorithm algo( 1, 2 );
|
||||
ParallelApplyStore< vector<int> > store( w, 0 );
|
||||
ParallelApplyStore< SerializableVector< SerializableBase<int> > > store( w, 0 );
|
||||
store.data( metaV );
|
||||
ParallelApply< vector<int> > job( algo, 0, store );
|
||||
ParallelApply< SerializableVector< SerializableBase<int> > > job( algo, 0, store );
|
||||
job.run();
|
||||
if( job.isMaster() )
|
||||
{
|
||||
|
|
|
|||
169
eo/test/mpi/t-mpi-multistart.cpp
Normal file
169
eo/test/mpi/t-mpi-multistart.cpp
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
# include <mpi/eoMultiStart.h>
|
||||
using namespace eo::mpi;
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <eo>
|
||||
#include <es.h>
|
||||
|
||||
/*
|
||||
* This file is based on the tutorial lesson 1. We'll consider that you know all the EO
|
||||
* related parts of the algorithm and we'll focus our attention on parallelization.
|
||||
*
|
||||
* This file shows an example of multistart applied to a eoSGA (simple genetic
|
||||
* algorithm). As individuals need to be serialized, we implement a class inheriting
|
||||
* from eoReal (which is the base individual), so as to manipulate individuals as they
|
||||
* were eoReal AND serialize them.
|
||||
*
|
||||
* The main function shows how to launch a multistart job, with default functors. If you
|
||||
* don't know which functors to use, these ones should fit the most of your purposes.
|
||||
*/
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* eoReal is a vector of double: we just have to serializes the value and the fitness.
|
||||
*/
|
||||
class SerializableEOReal: public eoReal<double>, public eoserial::Persistent
|
||||
{
|
||||
public:
|
||||
|
||||
SerializableEOReal(unsigned size = 0, double value = 0.0) :
|
||||
eoReal<double>(size, value)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
void unpack( const eoserial::Object* obj )
|
||||
{
|
||||
this->clear();
|
||||
eoserial::unpackArray
|
||||
< std::vector<double>, eoserial::Array::UnpackAlgorithm >
|
||||
( *obj, "vector", *this );
|
||||
|
||||
bool invalidFitness;
|
||||
eoserial::unpack( *obj, "invalid_fitness", invalidFitness );
|
||||
if( invalidFitness )
|
||||
{
|
||||
this->invalidate();
|
||||
} else
|
||||
{
|
||||
double f;
|
||||
eoserial::unpack( *obj, "fitness", f );
|
||||
this->fitness( f );
|
||||
}
|
||||
}
|
||||
|
||||
eoserial::Object* pack( void ) const
|
||||
{
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
obj->add( "vector", eoserial::makeArray< std::vector<double>, eoserial::MakeAlgorithm >( *this ) );
|
||||
|
||||
bool invalidFitness = this->invalid();
|
||||
obj->add( "invalid_fitness", eoserial::make( invalidFitness ) );
|
||||
if( !invalidFitness )
|
||||
{
|
||||
obj->add( "fitness", eoserial::make( this->fitness() ) );
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
// REPRESENTATION
|
||||
//-----------------------------------------------------------------------------
|
||||
// define your individuals
|
||||
typedef SerializableEOReal Indi;
|
||||
|
||||
// EVAL
|
||||
//-----------------------------------------------------------------------------
|
||||
// a simple fitness function that computes the euclidian norm of a real vector
|
||||
// @param _indi A real-valued individual
|
||||
|
||||
double real_value(const Indi & _indi)
|
||||
{
|
||||
double sum = 0;
|
||||
for (unsigned i = 0; i < _indi.size(); i++)
|
||||
sum += _indi[i]*_indi[i];
|
||||
return (-sum); // maximizing only
|
||||
}
|
||||
|
||||
/************************** PARALLELIZATION JOB *******************************/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Node::init( argc, argv );
|
||||
|
||||
// PARAMETRES
|
||||
// all parameters are hard-coded!
|
||||
const unsigned int SEED = 133742; // seed for random number generator
|
||||
const unsigned int VEC_SIZE = 8; // Number of object variables in genotypes
|
||||
const unsigned int POP_SIZE = 100; // Size of population
|
||||
const unsigned int T_SIZE = 3; // size for tournament selection
|
||||
const unsigned int MAX_GEN = 100; // Maximum number of generation before STOP
|
||||
const float CROSS_RATE = 0.8; // Crossover rate
|
||||
const double EPSILON = 0.01; // range for real uniform mutation
|
||||
const float MUT_RATE = 0.5; // mutation rate
|
||||
|
||||
eoEvalFuncPtr<Indi> eval( real_value );
|
||||
eoPop<Indi> pop;
|
||||
eoUniformGenerator< double > generator;
|
||||
eoInitFixedLength< Indi > init( VEC_SIZE, generator );
|
||||
pop = eoPop<Indi>( POP_SIZE, init );
|
||||
|
||||
eoDetTournamentSelect<Indi> select(T_SIZE);
|
||||
eoSegmentCrossover<Indi> xover;
|
||||
eoUniformMutation<Indi> mutation(EPSILON);
|
||||
|
||||
eoGenContinue<Indi> continuator(MAX_GEN);
|
||||
/* Does work too with a steady fit continuator. */
|
||||
// eoSteadyFitContinue< Indi > continuator( 10, 50 );
|
||||
|
||||
eoSGA<Indi> gga(select, xover, CROSS_RATE, mutation, MUT_RATE,
|
||||
eval, continuator);
|
||||
|
||||
/* How to assign tasks, which are starts? */
|
||||
DynamicAssignmentAlgorithm assignmentAlgo;
|
||||
/* Before a worker starts its algorithm, how does it reinits the population?
|
||||
* There are a few default usable functors, defined in eoMultiStart.h.
|
||||
*
|
||||
* This one (ReuseSamePopEA) doesn't modify the population after a start, so
|
||||
* the same population is reevaluated on each multistart: the solution tend
|
||||
* to get better and better.
|
||||
*/
|
||||
ReuseSamePopEA< Indi > resetAlgo( continuator, pop, eval );
|
||||
/**
|
||||
* How to send seeds to the workers, at the beginning of the parallel job?
|
||||
* This functors indicates that seeds should be random values.
|
||||
*/
|
||||
GetRandomSeeds< Indi > getSeeds( SEED );
|
||||
|
||||
// Builds the store
|
||||
MultiStartStore< Indi > store(
|
||||
gga,
|
||||
DEFAULT_MASTER,
|
||||
resetAlgo,
|
||||
getSeeds);
|
||||
|
||||
// Creates the multistart job and runs it.
|
||||
// The last argument indicates that we want to launch 5 runs.
|
||||
MultiStart< Indi > msjob( assignmentAlgo, DEFAULT_MASTER, store, 5 );
|
||||
msjob.run();
|
||||
|
||||
if( msjob.isMaster() )
|
||||
{
|
||||
msjob.best_individuals().sort();
|
||||
std::cout << "Global best individual has fitness " << msjob.best_individuals().best_element().fitness() << std::endl;
|
||||
}
|
||||
|
||||
MultiStart< Indi > msjob10( assignmentAlgo, DEFAULT_MASTER, store, 10 );
|
||||
msjob10.run();
|
||||
|
||||
if( msjob10.isMaster() )
|
||||
{
|
||||
msjob10.best_individuals().sort();
|
||||
std::cout << "Global best individual has fitness " << msjob10.best_individuals().best_element().fitness() << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -25,6 +25,9 @@ Authors:
|
|||
* incremented... in a parallel fashion. While this operation is very easy to perform even on a single host, it's just
|
||||
* an example for parallel apply use.
|
||||
*
|
||||
* The table of integers has to be serialized before it's sent. The wrapper object SerializableBase allows to serialize
|
||||
* any type and manipulate it like this type: SerializableBase<int> can be exactly be used as an integer.
|
||||
*
|
||||
* Besides, this is also a test for assignment (scheduling) algorithms, in different cases. The test succeeds if and
|
||||
* only if the program terminates without any segfault ; otherwise, there could be a deadlock which prevents the end or
|
||||
* a segfault at any time.
|
||||
|
|
@ -40,7 +43,10 @@ Authors:
|
|||
# include <mpi/eoParallelApply.h>
|
||||
# include <mpi/eoTerminateJob.h>
|
||||
|
||||
# include "t-mpi-common.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <cstdlib>
|
||||
|
||||
# include <vector>
|
||||
using namespace std;
|
||||
|
|
@ -50,11 +56,11 @@ 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<int>&, void >
|
||||
{
|
||||
void operator() ( int & x )
|
||||
void operator() ( SerializableBase<int> & x )
|
||||
{
|
||||
++x;
|
||||
++x; // implicit conversion of SerializableBase<int> in the integer it contains
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -79,7 +85,7 @@ int main(int argc, char** argv)
|
|||
|
||||
// Initializes a vector with random values.
|
||||
srand( time(0) );
|
||||
vector<int> v;
|
||||
vector< SerializableBase<int> > v;
|
||||
for( int i = 0; i < 1000; ++i )
|
||||
{
|
||||
v.push_back( rand() );
|
||||
|
|
@ -90,7 +96,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<int> originalV = v;
|
||||
vector< SerializableBase<int> > originalV = v;
|
||||
|
||||
// Instanciates the functor to apply on each element
|
||||
plusOne plusOneInstance;
|
||||
|
|
@ -166,11 +172,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<int> > 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<int> > job( *(tests[i].assign), eo::mpi::DEFAULT_MASTER, store );
|
||||
|
||||
// Only master writes information
|
||||
if( job.isMaster() )
|
||||
|
|
|
|||
|
|
@ -33,7 +33,10 @@ Authors:
|
|||
# include <mpi/eoParallelApply.h>
|
||||
# include <mpi/eoTerminateJob.h>
|
||||
|
||||
# include "t-mpi-common.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <cstdlib>
|
||||
|
||||
# include <vector>
|
||||
using namespace std;
|
||||
|
|
@ -41,9 +44,9 @@ using namespace std;
|
|||
using namespace eo::mpi;
|
||||
|
||||
// Job functor.
|
||||
struct plusOne : public eoUF< int&, void >
|
||||
struct plusOne : public eoUF< SerializableBase<int>&, void >
|
||||
{
|
||||
void operator() ( int & x )
|
||||
void operator() ( SerializableBase<int>& x )
|
||||
{
|
||||
++x;
|
||||
}
|
||||
|
|
@ -83,28 +86,28 @@ int main(int argc, char** argv)
|
|||
Node::init( argc, argv );
|
||||
|
||||
srand( time(0) );
|
||||
vector<int> v;
|
||||
vector< SerializableBase<int> > v;
|
||||
for( int i = 0; i < 1000; ++i )
|
||||
{
|
||||
v.push_back( rand() );
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
vector<int> originalV = v;
|
||||
vector< SerializableBase<int> > originalV = v;
|
||||
|
||||
plusOne plusOneInstance;
|
||||
|
||||
StaticAssignmentAlgorithm assign( v.size() );
|
||||
|
||||
ParallelApplyStore< int > store( plusOneInstance, eo::mpi::DEFAULT_MASTER, 1 );
|
||||
ParallelApplyStore< SerializableBase<int> > 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<int>* wrapper = new ShowWrappedResult<int>;
|
||||
store.wrapIsFinished( wrapper );
|
||||
ShowWrappedResult< SerializableBase<int> > wrapper;
|
||||
store.wrapIsFinished( &wrapper );
|
||||
|
||||
ParallelApply<int> job( assign, eo::mpi::DEFAULT_MASTER, store );
|
||||
ParallelApply< SerializableBase<int> > job( assign, eo::mpi::DEFAULT_MASTER, store );
|
||||
// Equivalent to:
|
||||
// Job< ParallelApplyData<int> > job( assign, 0, store );
|
||||
job.run();
|
||||
|
|
@ -125,8 +128,6 @@ int main(int argc, char** argv)
|
|||
cout << endl;
|
||||
}
|
||||
|
||||
delete wrapper;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
104
eo/test/mpi/template-job.cpp
Normal file
104
eo/test/mpi/template-job.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# include <mpi/eoMpi.h>
|
||||
|
||||
using namespace eo::mpi;
|
||||
|
||||
/*
|
||||
* This file is a template for a new eo::mpi::Job. You have everything that should be necessary to implement a new
|
||||
* parallelized algorithm.
|
||||
*
|
||||
* Replace __TEMPLATE__ by the name of your algorithm (for instance: MultiStart, ParallelApply, etc.).
|
||||
*/
|
||||
|
||||
template< class EOT >
|
||||
struct __TEMPLATE__Data
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class SendTask__TEMPLATE__ : public SendTaskFunction< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
using SendTaskFunction< __TEMPLATE__Data< EOT > >::_data;
|
||||
|
||||
void operator()( int wrkRank )
|
||||
{
|
||||
// TODO implement me
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class HandleResponse__TEMPLATE__ : public HandleResponseFunction< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
using HandleResponseFunction< __TEMPLATE__Data< EOT > >::_data;
|
||||
|
||||
void operator()( int wrkRank )
|
||||
{
|
||||
// TODO implement me
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class ProcessTask__TEMPLATE__ : public ProcessTaskFunction< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
using ProcessTaskFunction< __TEMPLATE__Data<EOT> >::_data;
|
||||
|
||||
void operator()()
|
||||
{
|
||||
// TODO implement me
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class IsFinished__TEMPLATE__ : public IsFinishedFunction< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
using IsFinishedFunction< __TEMPLATE__Data< EOT > >::_data;
|
||||
|
||||
bool operator()()
|
||||
{
|
||||
// TODO implement me
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class __TEMPLATE__Store : public JobStore< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
__TEMPLATE__Data<EOT>* data()
|
||||
{
|
||||
// TODO implement me
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class __TEMPLATE__ : public MultiJob< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
__TEMPLATE__( AssignmentAlgorithm & algo,
|
||||
int masterRank,
|
||||
__TEMPLATE__Store< EOT > & store ) :
|
||||
MultiJob< __TEMPLATE__Data< EOT > >( algo, masterRank, store )
|
||||
{
|
||||
// TODO implement me
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Node::init( argc, argv );
|
||||
|
||||
DynamicAssignmentAlgorithm assignmentAlgo;
|
||||
__TEMPLATE__Store<int> store;
|
||||
__TEMPLATE__<int> job( assignmentAlgo, DEFAULT_MASTER, store );
|
||||
}
|
||||
*/
|
||||
Reference in a new issue