More constructors for assignment algorithms: by interval, by unique worker, by vector of ranks, or whole world.

This commit is contained in:
Benjamin Bouvier 2012-06-22 17:31:46 +02:00
commit f3cb5eec20
3 changed files with 142 additions and 33 deletions

View file

@ -2,7 +2,7 @@
# define __ASSIGNMENT_ALGORITHM_H__ # define __ASSIGNMENT_ALGORITHM_H__
# include <vector> # include <vector>
# include "MpiNode.h"
struct AssignmentAlgorithm struct AssignmentAlgorithm
{ {
virtual int get( ) = 0; virtual int get( ) = 0;
@ -14,6 +14,25 @@ struct AssignmentAlgorithm
struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm
{ {
public: 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<int> & workers )
{
availableWrk = workers;
}
DynamicAssignmentAlgorithm( int first, int last ) DynamicAssignmentAlgorithm( int first, int last )
{ {
for( int i = first; i <= last; ++i) for( int i = first; i <= last; ++i)
@ -55,11 +74,43 @@ struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm
struct StaticAssignmentAlgorithm : public AssignmentAlgorithm struct StaticAssignmentAlgorithm : public AssignmentAlgorithm
{ {
public: public:
StaticAssignmentAlgorithm( std::vector<int>& workers, int runs )
{
init( workers, runs );
}
StaticAssignmentAlgorithm( int first, int last, int runs ) StaticAssignmentAlgorithm( int first, int last, int runs )
{ {
unsigned int nbWorkers = last - first + 1; std::vector<int> workers;
for(int i = first; i <= last; ++i)
{
workers.push_back( i );
}
init( workers, runs );
}
StaticAssignmentAlgorithm( int runs )
{
std::vector<int> workers;
for(int i = 1; i < MpiNode::comm().size(); ++i)
{
workers.push_back( i );
}
init( workers, runs );
}
StaticAssignmentAlgorithm( int unique, int runs )
{
std::vector<int> workers;
workers.push_back( unique );
init( workers, runs );
}
private:
void init( std::vector<int> & workers, int runs )
{
unsigned int nbWorkers = workers.size();
freeWorkers = nbWorkers; freeWorkers = nbWorkers;
offset = first;
attributions.reserve( nbWorkers ); attributions.reserve( nbWorkers );
busy.resize( nbWorkers, false ); busy.resize( nbWorkers, false );
@ -71,8 +122,11 @@ struct StaticAssignmentAlgorithm : public AssignmentAlgorithm
// r requests to workers, in ascending order // r requests to workers, in ascending order
unsigned int diff = runs - (runs / nbWorkers) * nbWorkers; unsigned int diff = runs - (runs / nbWorkers) * nbWorkers;
for (unsigned int i = 0; i < diff; ++attributions[i++]); for (unsigned int i = 0; i < diff; ++attributions[i++]);
realRank = workers;
} }
public:
int get( ) int get( )
{ {
int assignee = -1; int assignee = -1;
@ -82,7 +136,7 @@ struct StaticAssignmentAlgorithm : public AssignmentAlgorithm
{ {
busy[i] = true; busy[i] = true;
--freeWorkers; --freeWorkers;
assignee = realRank( i ); assignee = realRank[ i ];
break; break;
} }
} }
@ -101,40 +155,35 @@ struct StaticAssignmentAlgorithm : public AssignmentAlgorithm
{ {
if( !busy[i] ) if( !busy[i] )
{ {
eo::log << "Idle : " << realRank(i) << eo::log << "Idle : " << realRank[i] <<
" / attributions : " << attributions[i] << std::endl; " / attributions : " << attributions[i] << std::endl;
ret.push_back( realRank(i) ); ret.push_back( realRank[i] );
} }
} }
afterIdle = true;
return ret; return ret;
} }
void confirm( int rank ) 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 ]; --attributions[ i ];
busy[ i ] = false; busy[ i ] = false;
++freeWorkers; ++freeWorkers;
} }
private: private:
int attributionsIndex( int rank )
{
return rank - offset;
}
int realRank( int index )
{
return index + offset;
}
std::vector<int> attributions; std::vector<int> attributions;
std::vector<int> realRank;
std::vector<bool> busy; std::vector<bool> busy;
bool afterIdle;
int runs;
int offset;
unsigned int freeWorkers; unsigned int freeWorkers;
}; };

View file

@ -61,7 +61,7 @@ int main(int argc, char** argv)
case 1: case 1:
{ {
// only one node is assigned to subjob mastering // only one node is assigned to subjob mastering
DynamicAssignmentAlgorithm algo( 1, 1 ); DynamicAssignmentAlgorithm algo( 1 );
ParallelApply< vector<int> > job( transmitInstance, metaV, algo, 0 ); ParallelApply< vector<int> > job( transmitInstance, metaV, algo, 0 );
job.run(); job.run();
if( job.isMaster() ) if( job.isMaster() )

View file

@ -18,8 +18,10 @@ struct Test
{ {
AssignmentAlgorithm * assign; AssignmentAlgorithm * assign;
string description; 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) int main(int argc, char** argv)
{ {
// eo::log << eo::setlevel( eo::debug ); // eo::log << eo::setlevel( eo::debug );
@ -32,24 +34,71 @@ int main(int argc, char** argv)
v.push_back(7); v.push_back(7);
v.push_back(42); v.push_back(42);
int offset = 0;
vector<int> originalV = v;
plusOne plusOneInstance; plusOne plusOneInstance;
vector< Test > tests; vector< Test > tests;
Test tStatic; const int ALL = MpiNode::comm().size();
tStatic.assign = new StaticAssignmentAlgorithm( 1, MpiNode::comm().size()-1, v.size() );
tStatic.description = "Correct static assignment."; Test tIntervalStatic;
tests.push_back( tStatic ); 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; 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.description = "Static assignment with too many runs.";
tStaticOverload.requiredNodesNumber = ALL;
tests.push_back( tStaticOverload ); tests.push_back( tStaticOverload );
Test tDynamic; Test tUniqueStatic;
tDynamic.assign = new DynamicAssignmentAlgorithm( 1, MpiNode::comm().size()-1 ); tUniqueStatic.assign = new StaticAssignmentAlgorithm( 1, v.size() );
tDynamic.description = "Dynamic assignment."; tUniqueStatic.description = "Correct static assignment with unique worker.";
tests.push_back( tDynamic ); 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 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 ) 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; cout << "Test : " << tests[i].description << endl;
} }
job.run(); if( MpiNode::comm().rank() < tests[i].requiredNodesNumber )
{
job.run();
}
if( job.isMaster() ) if( job.isMaster() )
{ {
++offset;
for(int i = 0; i < v.size(); ++i) for(int i = 0; i < v.size(); ++i)
{ {
cout << v[i] << ' '; cout << v[i] << ' ';
if( originalV[i] + offset != v[i] )
{
cout << " <-- ERROR at this point." << endl;
exit( EXIT_FAILURE );
}
} }
cout << endl; cout << endl;
} }
MpiNode::comm().barrier();
delete tests[i].assign; delete tests[i].assign;
} }
return 0; return 0;