Included MPI tests into compilation, if WITH_MPI is defined.
This commit is contained in:
parent
ad74755d8e
commit
d2816d530a
6 changed files with 73 additions and 2 deletions
|
|
@ -14,12 +14,23 @@ INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/contrib)
|
|||
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()
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries
|
||||
######################################################################################
|
||||
|
||||
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()
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets and link the librairies
|
||||
######################################################################################
|
||||
|
|
@ -65,8 +76,8 @@ SET (TEST_LIST
|
|||
t-eoExtendedVelocity
|
||||
t-eoLogger
|
||||
t-eoIQRStat
|
||||
t-eoParallel
|
||||
t-openmp
|
||||
#t-eoParallel
|
||||
#t-openmp
|
||||
#t-eoDualFitness
|
||||
t-eoParser
|
||||
)
|
||||
|
|
|
|||
55
eo/test/mpi/CMakeLists.txt
Normal file
55
eo/test/mpi/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
###############################################################################
|
||||
##
|
||||
## CMakeLists file for eo/test/mpi
|
||||
##
|
||||
###############################################################################
|
||||
|
||||
######################################################################################
|
||||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
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})
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries
|
||||
######################################################################################
|
||||
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
LINK_DIRECTORIES(${MPI_DIR}/lib)
|
||||
LINK_DIRECTORIES(${BOOST_DIR}/lib)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets and link the librairies
|
||||
######################################################################################
|
||||
|
||||
SET (TEST_LIST
|
||||
t-mpi-parallelApply
|
||||
t-mpi-wrapper
|
||||
t-mpi-multipleRoles
|
||||
t-mpi-eval
|
||||
)
|
||||
|
||||
FOREACH (test ${TEST_LIST})
|
||||
SET ("T_${test}_SOURCES" "${test}.cpp")
|
||||
ENDFOREACH (test)
|
||||
|
||||
SET(CMAKE_CXX_COMPILER "${MPI_DIR}/bin/mpicxx")
|
||||
ADD_DEFINITIONS(-DWITH_MPI)
|
||||
|
||||
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)
|
||||
INSTALL(TARGETS ${test} RUNTIME DESTINATION share/eo/test COMPONENT test)
|
||||
ENDFOREACH (test)
|
||||
ENDIF()
|
||||
|
||||
######################################################################################
|
||||
168
eo/test/mpi/t-mpi-eval.cpp
Normal file
168
eo/test/mpi/t-mpi-eval.cpp
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// t-eoMpiParallel.cpp
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <eo>
|
||||
#include <eoPopEvalFunc.h>
|
||||
|
||||
#include <es/make_real.h>
|
||||
// #include <apply.h>
|
||||
#include "../real_value.h"
|
||||
|
||||
#include <mpi/eoMpi.h>
|
||||
|
||||
#include <boost/mpi.hpp>
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class eoRealSerializable : public eoReal< eoMinimizingFitness >, public eoserial::Persistent
|
||||
{
|
||||
public:
|
||||
|
||||
eoRealSerializable(unsigned size = 0, double value = 0.0):
|
||||
eoReal<eoMinimizingFitness>(size, value) {}
|
||||
|
||||
eoserial::Object* pack() const
|
||||
{
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
obj->add( "array",
|
||||
eoserial::makeArray< vector<double>, eoserial::MakeAlgorithm >
|
||||
( *this )
|
||||
);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void unpack( const eoserial::Object* obj )
|
||||
{
|
||||
eoserial::unpackArray< vector<double>, eoserial::Array::UnpackAlgorithm >
|
||||
( *obj, "array", *this );
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
struct CatBestAnswers : public eo::mpi::HandleResponseParallelApply<EOT>
|
||||
{
|
||||
CatBestAnswers()
|
||||
{
|
||||
best.fitness( 1000000000. );
|
||||
}
|
||||
|
||||
using eo::mpi::HandleResponseParallelApply<EOT>::_wrapped;
|
||||
using eo::mpi::HandleResponseParallelApply<EOT>::d;
|
||||
|
||||
void operator()(int wrkRank)
|
||||
{
|
||||
int index = d->assignedTasks[wrkRank].index;
|
||||
int size = d->assignedTasks[wrkRank].size;
|
||||
(*_wrapped)( wrkRank );
|
||||
for(int i = index; i < index+size; ++i)
|
||||
{
|
||||
if( best.fitness() < d->data()[ i ].fitness() )
|
||||
{
|
||||
eo::log << eo::quiet << "Better solution found:" << d->data()[i].fitness() << std::endl;
|
||||
best = d->data()[ i ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
EOT best;
|
||||
};
|
||||
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
eo::mpi::Node::init( ac, av );
|
||||
eo::log << eo::setlevel( eo::quiet );
|
||||
|
||||
eoParser parser(ac, av);
|
||||
|
||||
unsigned int popSize = parser.getORcreateParam((unsigned int)100, "popSize", "Population Size", 'P', "Evolution Engine").value();
|
||||
unsigned int dimSize = parser.getORcreateParam((unsigned int)10, "dimSize", "Dimension Size", 'd', "Evolution Engine").value();
|
||||
|
||||
uint32_t seedParam = parser.getORcreateParam((uint32_t)0, "seed", "Random number seed", 0).value();
|
||||
if (seedParam == 0) { seedParam = time(0); }
|
||||
|
||||
make_parallel(parser);
|
||||
make_help(parser);
|
||||
|
||||
rng.reseed( seedParam );
|
||||
|
||||
eoUniformGenerator< double > gen(-5, 5);
|
||||
eoInitFixedLength< EOT > init( dimSize, gen );
|
||||
|
||||
eoEvalFuncPtr< EOT, double, const std::vector< double >& > mainEval( real_value );
|
||||
eoEvalFuncCounter< EOT > eval( mainEval );
|
||||
|
||||
int rank = eo::mpi::Node::comm().rank();
|
||||
eo::mpi::DynamicAssignmentAlgorithm assign;
|
||||
if( rank == eo::mpi::DEFAULT_MASTER )
|
||||
{
|
||||
eoPop< EOT > pop( popSize, init );
|
||||
|
||||
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 );
|
||||
eo::log << eo::quiet << "Before first evaluation." << std::endl;
|
||||
popEval( pop, pop );
|
||||
eo::log << eo::quiet << "After first evaluation." << std::endl;
|
||||
|
||||
pop = eoPop< EOT >( popSize, init );
|
||||
popEval( pop, pop );
|
||||
eo::log << eo::quiet << "After second evaluation." << std::endl;
|
||||
|
||||
eo::log << eo::quiet << "DONE!" << std::endl;
|
||||
} else
|
||||
{
|
||||
eoPop< EOT > pop( popSize, init );
|
||||
eoParallelPopLoopEval< EOT > popEval( assign, eo::mpi::DEFAULT_MASTER, eval );
|
||||
popEval( pop, pop );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
113
eo/test/mpi/t-mpi-multipleRoles.cpp
Normal file
113
eo/test/mpi/t-mpi-multipleRoles.cpp
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# include <mpi/eoMpi.h>
|
||||
# include <mpi/eoParallelApply.h>
|
||||
# include <mpi/eoTerminateJob.h>
|
||||
|
||||
# include <boost/serialization/vector.hpp>
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include <vector>
|
||||
using namespace std;
|
||||
|
||||
using namespace eo::mpi;
|
||||
|
||||
// Role map
|
||||
// 0 : general master
|
||||
// 1, 2 : worker of general job, master of subjob
|
||||
// 3 to 7 : workers of subjob
|
||||
|
||||
struct SubWork: public eoUF< int&, void >
|
||||
{
|
||||
void operator() ( int & x )
|
||||
{
|
||||
cout << "Subwork phase." << endl;
|
||||
++x;
|
||||
}
|
||||
};
|
||||
|
||||
void subtask( vector<int>& v, int rank )
|
||||
{
|
||||
vector<int> workers;
|
||||
workers.push_back( rank + 2 );
|
||||
workers.push_back( rank + 4 );
|
||||
DynamicAssignmentAlgorithm algo( workers );
|
||||
SubWork sw;
|
||||
|
||||
ParallelApplyStore<int> store( sw, rank );
|
||||
store.data( v );
|
||||
ParallelApply<int> job( algo, rank, store );
|
||||
job.run();
|
||||
EmptyJob stop( algo, rank );
|
||||
}
|
||||
|
||||
struct Work: public eoUF< vector<int>&, void >
|
||||
{
|
||||
void operator() ( vector<int>& v )
|
||||
{
|
||||
cout << "Work phase..." << endl;
|
||||
subtask( v, Node::comm().rank() );
|
||||
for( int i = 0; i < v.size(); ++i )
|
||||
{
|
||||
v[i] *= 2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// eo::log << eo::setlevel( eo::debug );
|
||||
Node::init( argc, argv );
|
||||
vector<int> v;
|
||||
|
||||
v.push_back(1);
|
||||
v.push_back(3);
|
||||
v.push_back(3);
|
||||
v.push_back(7);
|
||||
v.push_back(42);
|
||||
|
||||
vector< vector<int> > metaV;
|
||||
metaV.push_back( v );
|
||||
metaV.push_back( v );
|
||||
|
||||
switch( Node::comm().rank() )
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
{
|
||||
Work w;
|
||||
DynamicAssignmentAlgorithm algo( 1, 2 );
|
||||
ParallelApplyStore< vector<int> > store( w, 0 );
|
||||
store.data( metaV );
|
||||
ParallelApply< vector<int> > job( algo, 0, store );
|
||||
job.run();
|
||||
if( job.isMaster() )
|
||||
{
|
||||
EmptyJob stop( algo, 0 );
|
||||
v = metaV[0];
|
||||
cout << "Results : " << endl;
|
||||
for(int i = 0; i < v.size(); ++i)
|
||||
{
|
||||
cout << v[i] << ' ';
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// all the other nodes are sub workers
|
||||
int rank = Node::comm().rank();
|
||||
if ( rank == 3 or rank == 5 )
|
||||
{
|
||||
subtask( v, 1 );
|
||||
} else {
|
||||
subtask( v, 2 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
150
eo/test/mpi/t-mpi-parallelApply.cpp
Normal file
150
eo/test/mpi/t-mpi-parallelApply.cpp
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
# include <mpi/eoMpi.h>
|
||||
# include <mpi/eoParallelApply.h>
|
||||
# include <mpi/eoTerminateJob.h>
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include <vector>
|
||||
using namespace std;
|
||||
|
||||
using namespace eo::mpi;
|
||||
|
||||
struct plusOne : public eoUF< int&, void >
|
||||
{
|
||||
void operator() ( int & x )
|
||||
{
|
||||
++x;
|
||||
}
|
||||
};
|
||||
|
||||
struct Test
|
||||
{
|
||||
AssignmentAlgorithm * assign;
|
||||
string description;
|
||||
int requiredNodesNumber; // nb : chosen nodes ranks must be sequential
|
||||
};
|
||||
|
||||
// These tests require at least 3 processes to be launched.
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// eo::log << eo::setlevel( eo::debug );
|
||||
eo::log << eo::setlevel( eo::quiet );
|
||||
bool launchOnlyOne = false ; // Set this to true if you wanna launch only the first test.
|
||||
|
||||
Node::init( argc, argv );
|
||||
|
||||
srand( time(0) );
|
||||
vector<int> v;
|
||||
for( int i = 0; i < 1000; ++i )
|
||||
{
|
||||
v.push_back( rand() );
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
vector<int> originalV = v;
|
||||
|
||||
plusOne plusOneInstance;
|
||||
|
||||
vector< Test > tests;
|
||||
|
||||
const int ALL = Node::comm().size();
|
||||
|
||||
Test tIntervalStatic;
|
||||
tIntervalStatic.assign = new StaticAssignmentAlgorithm( 1, REST_OF_THE_WORLD, v.size() );
|
||||
tIntervalStatic.description = "Correct static assignment with interval.";
|
||||
tIntervalStatic.requiredNodesNumber = ALL;
|
||||
tests.push_back( tIntervalStatic );
|
||||
|
||||
if( !launchOnlyOne )
|
||||
{
|
||||
Test tWorldStatic;
|
||||
tWorldStatic.assign = new StaticAssignmentAlgorithm( v.size() );
|
||||
tWorldStatic.description = "Correct static assignment with whole world as workers.";
|
||||
tWorldStatic.requiredNodesNumber = ALL;
|
||||
tests.push_back( tWorldStatic );
|
||||
|
||||
Test tStaticOverload;
|
||||
tStaticOverload.assign = new StaticAssignmentAlgorithm( v.size()+100 );
|
||||
tStaticOverload.description = "Static assignment with too many runs.";
|
||||
tStaticOverload.requiredNodesNumber = ALL;
|
||||
tests.push_back( tStaticOverload );
|
||||
|
||||
Test tUniqueStatic;
|
||||
tUniqueStatic.assign = new StaticAssignmentAlgorithm( 1, v.size() );
|
||||
tUniqueStatic.description = "Correct static assignment with unique worker.";
|
||||
tUniqueStatic.requiredNodesNumber = 2;
|
||||
tests.push_back( tUniqueStatic );
|
||||
|
||||
Test tVectorStatic;
|
||||
vector<int> workers;
|
||||
workers.push_back( 1 );
|
||||
workers.push_back( 2 );
|
||||
tVectorStatic.assign = new StaticAssignmentAlgorithm( workers, v.size() );
|
||||
tVectorStatic.description = "Correct static assignment with precise workers specified.";
|
||||
tVectorStatic.requiredNodesNumber = 3;
|
||||
tests.push_back( tVectorStatic );
|
||||
|
||||
Test tIntervalDynamic;
|
||||
tIntervalDynamic.assign = new DynamicAssignmentAlgorithm( 1, REST_OF_THE_WORLD );
|
||||
tIntervalDynamic.description = "Dynamic assignment with interval.";
|
||||
tIntervalDynamic.requiredNodesNumber = ALL;
|
||||
tests.push_back( tIntervalDynamic );
|
||||
|
||||
Test tUniqueDynamic;
|
||||
tUniqueDynamic.assign = new DynamicAssignmentAlgorithm( 1 );
|
||||
tUniqueDynamic.description = "Dynamic assignment with unique worker.";
|
||||
tUniqueDynamic.requiredNodesNumber = 2;
|
||||
tests.push_back( tUniqueDynamic );
|
||||
|
||||
Test tVectorDynamic;
|
||||
tVectorDynamic.assign = new DynamicAssignmentAlgorithm( workers );
|
||||
tVectorDynamic.description = "Dynamic assignment with precise workers specified.";
|
||||
tVectorDynamic.requiredNodesNumber = tVectorStatic.requiredNodesNumber;
|
||||
tests.push_back( tVectorDynamic );
|
||||
|
||||
Test tWorldDynamic;
|
||||
tWorldDynamic.assign = new DynamicAssignmentAlgorithm;
|
||||
tWorldDynamic.description = "Dynamic assignment with whole world as workers.";
|
||||
tWorldDynamic.requiredNodesNumber = ALL;
|
||||
tests.push_back( tWorldDynamic );
|
||||
}
|
||||
|
||||
for( unsigned int i = 0; i < tests.size(); ++i )
|
||||
{
|
||||
ParallelApplyStore< int > store( plusOneInstance, eo::mpi::DEFAULT_MASTER, 3 );
|
||||
store.data( v );
|
||||
ParallelApply< int > job( *(tests[i].assign), eo::mpi::DEFAULT_MASTER, store );
|
||||
|
||||
if( job.isMaster() )
|
||||
{
|
||||
cout << "Test : " << tests[i].description << endl;
|
||||
}
|
||||
|
||||
if( Node::comm().rank() < tests[i].requiredNodesNumber )
|
||||
{
|
||||
job.run();
|
||||
}
|
||||
|
||||
if( job.isMaster() )
|
||||
{
|
||||
EmptyJob stop( *(tests[i].assign), eo::mpi::DEFAULT_MASTER );
|
||||
++offset;
|
||||
for(int i = 0; i < v.size(); ++i)
|
||||
{
|
||||
cout << v[i] << ' ';
|
||||
if( originalV[i] + offset != v[i] )
|
||||
{
|
||||
cout << " <-- ERROR at this point." << endl;
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
Node::comm().barrier();
|
||||
|
||||
delete tests[i].assign;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
91
eo/test/mpi/t-mpi-wrapper.cpp
Normal file
91
eo/test/mpi/t-mpi-wrapper.cpp
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# include <mpi/eoMpi.h>
|
||||
# include <mpi/eoParallelApply.h>
|
||||
# include <mpi/eoTerminateJob.h>
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include <vector>
|
||||
using namespace std;
|
||||
|
||||
using namespace eo::mpi;
|
||||
|
||||
struct plusOne : public eoUF< int&, void >
|
||||
{
|
||||
void operator() ( int & x )
|
||||
{
|
||||
++x;
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
struct ShowWrappedResult : public IsFinishedParallelApply<EOT>
|
||||
{
|
||||
using IsFinishedParallelApply<EOT>::_wrapped;
|
||||
|
||||
ShowWrappedResult ( IsFinishedParallelApply<EOT> * w = 0 ) : IsFinishedParallelApply<EOT>( w ), times( 0 )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
bool operator()()
|
||||
{
|
||||
bool wrappedValue = _wrapped->operator()(); // (*_wrapped)();
|
||||
cout << times << ") Wrapped function would say that it is " << ( wrappedValue ? "":"not ") << "finished" << std::endl;
|
||||
++times;
|
||||
return wrappedValue;
|
||||
}
|
||||
|
||||
private:
|
||||
int times;
|
||||
};
|
||||
|
||||
// These tests require at least 3 processes to be launched.
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// eo::log << eo::setlevel( eo::debug );
|
||||
eo::log << eo::setlevel( eo::quiet );
|
||||
|
||||
Node::init( argc, argv );
|
||||
|
||||
srand( time(0) );
|
||||
vector<int> v;
|
||||
for( int i = 0; i < 1000; ++i )
|
||||
{
|
||||
v.push_back( rand() );
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
vector<int> originalV = v;
|
||||
|
||||
plusOne plusOneInstance;
|
||||
|
||||
StaticAssignmentAlgorithm assign( v.size() );
|
||||
|
||||
ParallelApplyStore< int > store( plusOneInstance, eo::mpi::DEFAULT_MASTER, 1 );
|
||||
store.data( v );
|
||||
store.wrapIsFinished( new ShowWrappedResult<int> );
|
||||
|
||||
ParallelApply<int> job( assign, eo::mpi::DEFAULT_MASTER, store );
|
||||
// Equivalent to:
|
||||
// Job< ParallelApplyData<int> > job( assign, 0, store );
|
||||
job.run();
|
||||
EmptyJob stop( assign, eo::mpi::DEFAULT_MASTER );
|
||||
|
||||
if( job.isMaster() )
|
||||
{
|
||||
++offset;
|
||||
for(int i = 0; i < v.size(); ++i)
|
||||
{
|
||||
cout << v[i] << ' ';
|
||||
if( originalV[i] + offset != v[i] )
|
||||
{
|
||||
cout << " <-- ERROR at this point." << endl;
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in a new issue