# ifndef __MPI_ASSIGNMENT_ALGORITHM_H__ # define __MPI_ASSIGNMENT_ALGORITHM_H__ # include # include "eoMpiNode.h" namespace eo { namespace mpi { const int REST_OF_THE_WORLD = -1; struct AssignmentAlgorithm { virtual int get( ) = 0; virtual int availableWorkers( ) = 0; virtual void confirm( int wrkRank ) = 0; virtual std::vector idles( ) = 0; }; struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm { public: DynamicAssignmentAlgorithm( ) { for(int i = 1; i < Node::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 ) { if( last == REST_OF_THE_WORLD ) { last = Node::comm().size() - 1; } for( int i = first; i <= last; ++i) { availableWrk.push_back( i ); } } virtual int get( ) { int assignee = -1; if (! availableWrk.empty() ) { assignee = availableWrk.back(); availableWrk.pop_back(); } return assignee; } int availableWorkers() { return availableWrk.size(); } void confirm( int rank ) { availableWrk.push_back( rank ); } std::vector idles( ) { return availableWrk; } protected: std::vector< int > availableWrk; }; struct StaticAssignmentAlgorithm : public AssignmentAlgorithm { public: StaticAssignmentAlgorithm( std::vector& workers, int runs ) { init( workers, runs ); } StaticAssignmentAlgorithm( int first, int last, int runs ) { std::vector workers; if( last == REST_OF_THE_WORLD ) { last = Node::comm().size() - 1; } 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 < Node::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; attributions.reserve( nbWorkers ); busy.resize( nbWorkers, false ); // Let be the euclidean division of runs by nbWorkers : // runs == q * nbWorkers + r, 0 <= r < nbWorkers // This one liner affects q requests to each worker for (unsigned int i = 0; i < nbWorkers; attributions[i++] = runs / nbWorkers) ; // The first line computes r and the one liner affects the remaining // 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; for( unsigned i = 0; i < busy.size(); ++i ) { if( !busy[i] && attributions[i] > 0 ) { busy[i] = true; --freeWorkers; assignee = realRank[ i ]; break; } } return assignee; } int availableWorkers( ) { return freeWorkers; } std::vector idles() { std::vector ret; for(unsigned int i = 0; i < busy.size(); ++i) { if( !busy[i] ) { ret.push_back( realRank[i] ); } } return ret; } void confirm( int rank ) { int i = -1; for( unsigned int j = 0; j < realRank.size(); ++j ) { if( realRank[j] == rank ) { i = j; break; } } --attributions[ i ]; busy[ i ] = false; ++freeWorkers; } private: std::vector attributions; std::vector realRank; std::vector busy; unsigned int freeWorkers; }; } } # endif // __MPI_ASSIGNMENT_ALGORITHM_H__