From f3cb5eec20229df974865bcccd0dd004d613961b Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 22 Jun 2012 17:31:46 +0200 Subject: [PATCH] More constructors for assignment algorithms: by interval, by unique worker, by vector of ranks, or whole world. --- eo/src/mpi/assignmentAlgorithm.h | 93 ++++++++++++++++++++++++-------- eo/test/mpi/multipleRoles.cpp | 2 +- eo/test/mpi/parallelApply.cpp | 80 +++++++++++++++++++++++---- 3 files changed, 142 insertions(+), 33 deletions(-) diff --git a/eo/src/mpi/assignmentAlgorithm.h b/eo/src/mpi/assignmentAlgorithm.h index 06d3ec49..58fc09c0 100644 --- a/eo/src/mpi/assignmentAlgorithm.h +++ b/eo/src/mpi/assignmentAlgorithm.h @@ -2,7 +2,7 @@ # define __ASSIGNMENT_ALGORITHM_H__ # include - +# include "MpiNode.h" struct AssignmentAlgorithm { virtual int get( ) = 0; @@ -14,6 +14,25 @@ struct AssignmentAlgorithm struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm { public: + + DynamicAssignmentAlgorithm( ) + { + for(int i = 1; i < MpiNode::comm().size(); ++i) + { + availableWrk.push_back( i ); + } + } + + DynamicAssignmentAlgorithm( int unique ) + { + availableWrk.push_back( unique ); + } + + DynamicAssignmentAlgorithm( const std::vector & workers ) + { + availableWrk = workers; + } + DynamicAssignmentAlgorithm( int first, int last ) { for( int i = first; i <= last; ++i) @@ -55,11 +74,43 @@ struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm struct StaticAssignmentAlgorithm : public AssignmentAlgorithm { public: + StaticAssignmentAlgorithm( std::vector& workers, int runs ) + { + init( workers, runs ); + } + StaticAssignmentAlgorithm( int first, int last, int runs ) { - unsigned int nbWorkers = last - first + 1; + std::vector workers; + for(int i = first; i <= last; ++i) + { + workers.push_back( i ); + } + init( workers, runs ); + } + + StaticAssignmentAlgorithm( int runs ) + { + std::vector workers; + for(int i = 1; i < MpiNode::comm().size(); ++i) + { + workers.push_back( i ); + } + init( workers, runs ); + } + + StaticAssignmentAlgorithm( int unique, int runs ) + { + std::vector workers; + workers.push_back( unique ); + init( workers, runs ); + } + +private: + void init( std::vector & workers, int runs ) + { + unsigned int nbWorkers = workers.size(); freeWorkers = nbWorkers; - offset = first; attributions.reserve( nbWorkers ); busy.resize( nbWorkers, false ); @@ -71,8 +122,11 @@ struct StaticAssignmentAlgorithm : public AssignmentAlgorithm // r requests to workers, in ascending order unsigned int diff = runs - (runs / nbWorkers) * nbWorkers; for (unsigned int i = 0; i < diff; ++attributions[i++]); + + realRank = workers; } +public: int get( ) { int assignee = -1; @@ -82,7 +136,7 @@ struct StaticAssignmentAlgorithm : public AssignmentAlgorithm { busy[i] = true; --freeWorkers; - assignee = realRank( i ); + assignee = realRank[ i ]; break; } } @@ -101,40 +155,35 @@ struct StaticAssignmentAlgorithm : public AssignmentAlgorithm { if( !busy[i] ) { - eo::log << "Idle : " << realRank(i) << + eo::log << "Idle : " << realRank[i] << " / attributions : " << attributions[i] << std::endl; - ret.push_back( realRank(i) ); + ret.push_back( realRank[i] ); } } - afterIdle = true; return ret; } void confirm( int rank ) { - int i = attributionsIndex( rank ); + int i = -1; + for( int j = 0; j < realRank.size(); ++j ) + { + if( realRank[j] == rank ) + { + i = j; + break; + } + } + --attributions[ i ]; busy[ i ] = false; ++freeWorkers; } private: - int attributionsIndex( int rank ) - { - return rank - offset; - } - - int realRank( int index ) - { - return index + offset; - } - std::vector attributions; + std::vector realRank; std::vector busy; - - bool afterIdle; - int runs; - int offset; unsigned int freeWorkers; }; diff --git a/eo/test/mpi/multipleRoles.cpp b/eo/test/mpi/multipleRoles.cpp index a45dec42..a374def5 100644 --- a/eo/test/mpi/multipleRoles.cpp +++ b/eo/test/mpi/multipleRoles.cpp @@ -61,7 +61,7 @@ int main(int argc, char** argv) case 1: { // only one node is assigned to subjob mastering - DynamicAssignmentAlgorithm algo( 1, 1 ); + DynamicAssignmentAlgorithm algo( 1 ); ParallelApply< vector > job( transmitInstance, metaV, algo, 0 ); job.run(); if( job.isMaster() ) diff --git a/eo/test/mpi/parallelApply.cpp b/eo/test/mpi/parallelApply.cpp index 278ffd06..3fd77dc1 100644 --- a/eo/test/mpi/parallelApply.cpp +++ b/eo/test/mpi/parallelApply.cpp @@ -18,8 +18,10 @@ 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 ); @@ -32,24 +34,71 @@ int main(int argc, char** argv) v.push_back(7); v.push_back(42); + int offset = 0; + vector originalV = v; + plusOne plusOneInstance; vector< Test > tests; + + const int ALL = MpiNode::comm().size(); - Test tStatic; - tStatic.assign = new StaticAssignmentAlgorithm( 1, MpiNode::comm().size()-1, v.size() ); - tStatic.description = "Correct static assignment."; - tests.push_back( tStatic ); + Test tIntervalStatic; + tIntervalStatic.assign = new StaticAssignmentAlgorithm( 1, MpiNode::comm().size()-1, v.size() ); + tIntervalStatic.description = "Correct static assignment with interval."; + tIntervalStatic.requiredNodesNumber = ALL; + tests.push_back( tIntervalStatic ); + + 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( 1, MpiNode::comm().size()-1, v.size()+100 ); + tStaticOverload.assign = new StaticAssignmentAlgorithm( v.size()+100 ); tStaticOverload.description = "Static assignment with too many runs."; + tStaticOverload.requiredNodesNumber = ALL; tests.push_back( tStaticOverload ); - Test tDynamic; - tDynamic.assign = new DynamicAssignmentAlgorithm( 1, MpiNode::comm().size()-1 ); - tDynamic.description = "Dynamic assignment."; - tests.push_back( tDynamic ); + 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 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 StaticAssignmentAlgorithm( 1, MpiNode::comm().size()-1, v.size() ); + tIntervalDynamic.description = "Correct static assignment with interval."; + tIntervalDynamic.requiredNodesNumber = ALL; + tests.push_back( tIntervalDynamic ); + + Test tUniqueDynamic; + tUniqueDynamic.assign = new StaticAssignmentAlgorithm( 1, v.size() ); + tUniqueDynamic.description = "Correct static assignment with unique worker."; + tUniqueDynamic.requiredNodesNumber = 2; + tests.push_back( tUniqueDynamic ); + + Test tVectorDynamic; + tVectorDynamic.assign = new StaticAssignmentAlgorithm( workers, v.size() ); + tVectorDynamic.description = "Correct static assignment with precise workers specified."; + tVectorDynamic.requiredNodesNumber = tVectorStatic.requiredNodesNumber; + tests.push_back( tVectorDynamic ); + + Test tWorldDynamic; + tWorldDynamic.assign = new StaticAssignmentAlgorithm( v.size() ); + tWorldDynamic.description = "Correct static assignment with whole world as workers."; + tWorldDynamic.requiredNodesNumber = ALL; + tests.push_back( tWorldDynamic ); for( unsigned int i = 0; i < tests.size(); ++i ) { @@ -60,17 +109,28 @@ int main(int argc, char** argv) cout << "Test : " << tests[i].description << endl; } - job.run(); + if( MpiNode::comm().rank() < tests[i].requiredNodesNumber ) + { + job.run(); + } 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; } + MpiNode::comm().barrier(); + delete tests[i].assign; } return 0;