More constructors for assignment algorithms: by interval, by unique worker, by vector of ranks, or whole world.
This commit is contained in:
parent
5bfcf4cd2c
commit
f3cb5eec20
3 changed files with 142 additions and 33 deletions
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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() )
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Reference in a new issue