mDocumentation of eo::mpi classes.
This commit is contained in:
parent
1eac497c4d
commit
5e76ba30b0
6 changed files with 409 additions and 14 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
# include "eoMpi.h"
|
# include "eoMpi.h"
|
||||||
|
|
||||||
// MpiNode* MpiNodeStore::singleton;
|
|
||||||
namespace eo
|
namespace eo
|
||||||
{
|
{
|
||||||
namespace mpi
|
namespace mpi
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ namespace eo
|
||||||
/**
|
/**
|
||||||
* @ingroup Parallel
|
* @ingroup Parallel
|
||||||
* @defgroup MPI Message Passing Interface parallelization
|
* @defgroup MPI Message Passing Interface parallelization
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -790,6 +791,10 @@ namespace eo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
# endif // __EO_MPI_H__
|
# endif // __EO_MPI_H__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,118 @@
|
||||||
|
/*
|
||||||
|
(c) Thales group, 2012
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation;
|
||||||
|
version 2 of the License.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Contact: http://eodev.sourceforge.net
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||||
|
*/
|
||||||
# ifndef __MPI_ASSIGNMENT_ALGORITHM_H__
|
# ifndef __MPI_ASSIGNMENT_ALGORITHM_H__
|
||||||
# define __MPI_ASSIGNMENT_ALGORITHM_H__
|
# define __MPI_ASSIGNMENT_ALGORITHM_H__
|
||||||
|
|
||||||
# include <vector>
|
# include <vector> // std::vector
|
||||||
# include "eoMpiNode.h"
|
# include "eoMpiNode.h"
|
||||||
|
|
||||||
namespace eo
|
namespace eo
|
||||||
{
|
{
|
||||||
namespace mpi
|
namespace mpi
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief Constant indicating to use all the resting available workers, in assignment algorithms constructor
|
||||||
|
* using an interval.
|
||||||
|
*/
|
||||||
const int REST_OF_THE_WORLD = -1;
|
const int REST_OF_THE_WORLD = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Contains informations on the available workers and allows to find assignees for jobs.
|
||||||
|
*
|
||||||
|
* Available workers are workers who aren't processing anything. When they've received an order, workers switch
|
||||||
|
* from the state "available" to the state "busy", and the master has to wait for their response for considering
|
||||||
|
* them available again.
|
||||||
|
*
|
||||||
|
* @ingroup Parallel
|
||||||
|
*/
|
||||||
struct AssignmentAlgorithm
|
struct AssignmentAlgorithm
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief Gets the rank of an available worker, so as to send it a task.
|
||||||
|
*
|
||||||
|
* @return The MPI rank of an available worker, or -1 if there is no available worker.
|
||||||
|
*/
|
||||||
virtual int get( ) = 0;
|
virtual int get( ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the number of total available workers.
|
||||||
|
*
|
||||||
|
* Before the first call, it is equal to the total number of present workers, as specified in the
|
||||||
|
* specific assignment algorithm constructor. It allows the Job class to know when all the responses have
|
||||||
|
* been received, by comparing this number to the total number of workers.
|
||||||
|
*
|
||||||
|
* @return Integer indicating how many workers are available.
|
||||||
|
*/
|
||||||
virtual int availableWorkers( ) = 0;
|
virtual int availableWorkers( ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reinject the worker of indicated rank in the available state.
|
||||||
|
*
|
||||||
|
* @param wrkRank The MPI rank of the worker who has finished its job.
|
||||||
|
*/
|
||||||
virtual void confirm( int wrkRank ) = 0;
|
virtual void confirm( int wrkRank ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Indicates who are the workers which do nothing.
|
||||||
|
*
|
||||||
|
* At the end of the algorithm, the master has to warn all the workers that it's done. All the workers mean,
|
||||||
|
* the workers which are currently processing data, and the other ones who could be waiting : the idles.
|
||||||
|
* This function indicates to the master which worker aren't doing anything.
|
||||||
|
*
|
||||||
|
* @param A std::vector containing all the MPI ranks of the idles workers.
|
||||||
|
*/
|
||||||
virtual std::vector<int> idles( ) = 0;
|
virtual std::vector<int> idles( ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reinitializes the assignment algorithm with the right number of runs.
|
||||||
|
*
|
||||||
|
* In fact, this is only useful for static assignment algorithm, which has to be reinitialized every time
|
||||||
|
* it's used, in the case of a Multi Job. It's the user's responsability to call this function.
|
||||||
|
*
|
||||||
|
* @todo Not really clean. Find a better way to do it.
|
||||||
|
*/
|
||||||
virtual void reinit( int runs ) = 0;
|
virtual void reinit( int runs ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Assignment (scheduling) algorithm which handles workers in a queue.
|
||||||
|
*
|
||||||
|
* With this assignment algorithm, workers are put in a queue and may be called an unlimited number of times.
|
||||||
|
* Whenever a worker returns, it is added to the queue, and it becomes available for the next call to get().
|
||||||
|
* The available workers are all located in the queue at any time, so the number of available workers is
|
||||||
|
* directly equal to the size of the queue.
|
||||||
|
*
|
||||||
|
* This kind of assignment is adapted for tasks whose execution time is stochastic or unknown, but without any
|
||||||
|
* warranty to be faster than other assignments.
|
||||||
|
*
|
||||||
|
* @ingroup Parallel
|
||||||
|
*/
|
||||||
struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm
|
struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Uses all the hosts whose rank is higher to 1, inclusive, as workers.
|
||||||
|
*/
|
||||||
DynamicAssignmentAlgorithm( )
|
DynamicAssignmentAlgorithm( )
|
||||||
{
|
{
|
||||||
for(int i = 1; i < Node::comm().size(); ++i)
|
for(int i = 1; i < Node::comm().size(); ++i)
|
||||||
|
|
@ -31,16 +121,33 @@ namespace eo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Uses the unique host with given rank as a worker.
|
||||||
|
*
|
||||||
|
* @param unique MPI rank of the unique worker.
|
||||||
|
*/
|
||||||
DynamicAssignmentAlgorithm( int unique )
|
DynamicAssignmentAlgorithm( int unique )
|
||||||
{
|
{
|
||||||
availableWrk.push_back( unique );
|
availableWrk.push_back( unique );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Uses the workers whose ranks are present in the argument as workers.
|
||||||
|
*
|
||||||
|
* @param workers std::vector containing MPI ranks of workers.
|
||||||
|
*/
|
||||||
DynamicAssignmentAlgorithm( const std::vector<int> & workers )
|
DynamicAssignmentAlgorithm( const std::vector<int> & workers )
|
||||||
{
|
{
|
||||||
availableWrk = workers;
|
availableWrk = workers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Uses a range of ranks as workers.
|
||||||
|
*
|
||||||
|
* @param first The first worker to be included (inclusive)
|
||||||
|
* @param last The last worker to be included (inclusive). If last == eo::mpi::REST_OF_THE_WORLD, all
|
||||||
|
* hosts whose rank is higher than first are taken.
|
||||||
|
*/
|
||||||
DynamicAssignmentAlgorithm( int first, int last )
|
DynamicAssignmentAlgorithm( int first, int last )
|
||||||
{
|
{
|
||||||
if( last == REST_OF_THE_WORLD )
|
if( last == REST_OF_THE_WORLD )
|
||||||
|
|
@ -90,14 +197,43 @@ namespace eo
|
||||||
std::vector< int > availableWrk;
|
std::vector< int > availableWrk;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Assignment algorithm which gives to each worker a precise number of tasks to do, in a round robin
|
||||||
|
* fashion.
|
||||||
|
*
|
||||||
|
* This scheduling algorithm attributes, at initialization or when calling reinit(), a fixed amount of runs to
|
||||||
|
* distribute to the workers. The amount of runs is then equally distributed between all workers ; if total
|
||||||
|
* number of runs is not a direct multiple of workers number, then remainding unaffected runs are distributed to
|
||||||
|
* workers from the first to the last, in a round-robin fashion.
|
||||||
|
*
|
||||||
|
* This scheduling should be used when the amount of runs can be computed or is fixed and when we guess that the
|
||||||
|
* duration of processing task will be the same for each run. There is no warranty that this algorithm is more
|
||||||
|
* or less efficient that another one. When having a doubt, use DynamicAssignmentAlgorithm.
|
||||||
|
*
|
||||||
|
* @ingroup Parallel
|
||||||
|
*/
|
||||||
struct StaticAssignmentAlgorithm : public AssignmentAlgorithm
|
struct StaticAssignmentAlgorithm : public AssignmentAlgorithm
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Uses a given precise set of workers.
|
||||||
|
*
|
||||||
|
* @param workers std::vector of MPI ranks of workers which will be used.
|
||||||
|
* @param runs Fixed amount of runs, strictly positive.
|
||||||
|
*/
|
||||||
StaticAssignmentAlgorithm( std::vector<int>& workers, int runs )
|
StaticAssignmentAlgorithm( std::vector<int>& workers, int runs )
|
||||||
{
|
{
|
||||||
init( workers, runs );
|
init( workers, runs );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Uses a range of workers.
|
||||||
|
*
|
||||||
|
* @param first The first MPI rank of worker to use
|
||||||
|
* @param last The last MPI rank of worker to use. If it's equal to REST_OF_THE_WORLD, then all the
|
||||||
|
* workers from the first one are taken as workers.
|
||||||
|
* @param runs Fixed amount of runs, strictly positive.
|
||||||
|
*/
|
||||||
StaticAssignmentAlgorithm( int first, int last, int runs )
|
StaticAssignmentAlgorithm( int first, int last, int runs )
|
||||||
{
|
{
|
||||||
std::vector<int> workers;
|
std::vector<int> workers;
|
||||||
|
|
@ -114,6 +250,12 @@ namespace eo
|
||||||
init( workers, runs );
|
init( workers, runs );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Uses all the hosts whose rank is higher than 1 (inclusive) as workers.
|
||||||
|
*
|
||||||
|
* @param runs Fixed amount of runs, strictly positive. If it's not set, you'll have to call reinit()
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
StaticAssignmentAlgorithm( int runs = 0 )
|
StaticAssignmentAlgorithm( int runs = 0 )
|
||||||
{
|
{
|
||||||
std::vector<int> workers;
|
std::vector<int> workers;
|
||||||
|
|
@ -125,6 +267,12 @@ namespace eo
|
||||||
init( workers, runs );
|
init( workers, runs );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Uses an unique host as worker.
|
||||||
|
*
|
||||||
|
* @param unique The MPI rank of the host which will be the worker.
|
||||||
|
* @param runs Fixed amount of runs, strictly positive.
|
||||||
|
*/
|
||||||
StaticAssignmentAlgorithm( int unique, int runs )
|
StaticAssignmentAlgorithm( int unique, int runs )
|
||||||
{
|
{
|
||||||
std::vector<int> workers;
|
std::vector<int> workers;
|
||||||
|
|
@ -133,15 +281,31 @@ namespace eo
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Initializes the static scheduling.
|
||||||
|
*
|
||||||
|
* Gives to each worker an equal attribution number, equal to runs / workers.size(), eventually plus one
|
||||||
|
* if number of workers is not a divisor of runs.
|
||||||
|
*
|
||||||
|
* @param workers Vector of hosts' ranks
|
||||||
|
* @param runs Fixed amount of runs, strictly positive.
|
||||||
|
*/
|
||||||
void init( std::vector<int> & workers, int runs )
|
void init( std::vector<int> & workers, int runs )
|
||||||
{
|
{
|
||||||
unsigned int nbWorkers = workers.size();
|
unsigned int nbWorkers = workers.size();
|
||||||
freeWorkers = nbWorkers;
|
freeWorkers = nbWorkers;
|
||||||
|
|
||||||
attributions.clear();
|
|
||||||
attributions.reserve( nbWorkers );
|
|
||||||
busy.clear();
|
busy.clear();
|
||||||
busy.resize( nbWorkers, false );
|
busy.resize( nbWorkers, false );
|
||||||
|
realRank = workers;
|
||||||
|
|
||||||
|
if( runs <= 0 )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributions.clear();
|
||||||
|
attributions.reserve( nbWorkers );
|
||||||
|
|
||||||
// Let be the euclidean division of runs by nbWorkers :
|
// Let be the euclidean division of runs by nbWorkers :
|
||||||
// runs == q * nbWorkers + r, 0 <= r < nbWorkers
|
// runs == q * nbWorkers + r, 0 <= r < nbWorkers
|
||||||
|
|
@ -151,8 +315,6 @@ namespace eo
|
||||||
// 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:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,24 @@
|
||||||
|
/*
|
||||||
|
(c) Thales group, 2012
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation;
|
||||||
|
version 2 of the License.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Contact: http://eodev.sourceforge.net
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||||
|
*/
|
||||||
# ifndef __MPI_NODE_H__
|
# ifndef __MPI_NODE_H__
|
||||||
# define __MPI_NODE_H__
|
# define __MPI_NODE_H__
|
||||||
|
|
||||||
|
|
@ -8,15 +29,34 @@ namespace eo
|
||||||
{
|
{
|
||||||
namespace mpi
|
namespace mpi
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief Global object used to reach boost::mpi::communicator everywhere.
|
||||||
|
*
|
||||||
|
* boost::mpi::communicator is the main object used to send and receive messages between the different hosts of
|
||||||
|
* a MPI algorithm.
|
||||||
|
*
|
||||||
|
* @ingroup Parallel
|
||||||
|
*/
|
||||||
class Node
|
class Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the MPI environment with argc and argv.
|
||||||
|
*
|
||||||
|
* Should be called at the beginning of every parallel program.
|
||||||
|
*
|
||||||
|
* @param argc Main's argc
|
||||||
|
* @param argv Main's argv
|
||||||
|
*/
|
||||||
static void init( int argc, char** argv )
|
static void init( int argc, char** argv )
|
||||||
{
|
{
|
||||||
static bmpi::environment env( argc, argv );
|
static bmpi::environment env( argc, argv );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the global boost::mpi::communicator
|
||||||
|
*/
|
||||||
static bmpi::communicator& comm()
|
static bmpi::communicator& comm()
|
||||||
{
|
{
|
||||||
return _comm;
|
return _comm;
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,100 @@
|
||||||
|
/*
|
||||||
|
(c) Thales group, 2012
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation;
|
||||||
|
version 2 of the License.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Contact: http://eodev.sourceforge.net
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||||
|
*/
|
||||||
# ifndef __EO_PARALLEL_APPLY_H__
|
# ifndef __EO_PARALLEL_APPLY_H__
|
||||||
# define __EO_PARALLEL_APPLY_H__
|
# define __EO_PARALLEL_APPLY_H__
|
||||||
|
|
||||||
# include "eoMpi.h"
|
# include "eoMpi.h"
|
||||||
|
|
||||||
# include <eoFunctor.h>
|
# include <eoFunctor.h> // eoUF
|
||||||
# include <vector>
|
# include <vector> // std::vector population
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file eoParallelApply.h
|
||||||
|
*
|
||||||
|
* @brief Applies a functor with single parameter to elements of a table, in a parallel fashion.
|
||||||
|
*
|
||||||
|
* This file contains all the required classes to do a parallel apply of a table, in a parallel fashion. This can be
|
||||||
|
* very useful when applying the function can be made without any dependances within the data. In EO, it occurs in
|
||||||
|
* particular during the evaluation: the number of individuals to evaluate can be really high, and the evaluation of one
|
||||||
|
* individual is independant from the evaluation of other individuals.
|
||||||
|
*
|
||||||
|
* Elements in the table are directly replaced, as the table is given by reference. No new table is made during the
|
||||||
|
* process.
|
||||||
|
*
|
||||||
|
* User can tune this job, indicating how many elements of the table should be sent and evaluated by a worker, at a
|
||||||
|
* time: this is called the "packet size", as individuals are groupped into a packet of individuals which are sent to
|
||||||
|
* the worker before evaluation. The problem of choosing the optimal packet size is beyond the purposes of this documentation
|
||||||
|
* and deserves a theoritical study.
|
||||||
|
*
|
||||||
|
* This job is the parallel equivalent to the function apply<EOT>, defined in apply.h. It just applies the function to
|
||||||
|
* every element of a table. In Python or Javascript, it's the equivalent of the function Map.
|
||||||
|
*/
|
||||||
|
|
||||||
namespace eo
|
namespace eo
|
||||||
{
|
{
|
||||||
namespace mpi
|
namespace mpi
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief Structure used to save assignment to a worker, i.e which slice of the table it has to process.
|
||||||
|
*
|
||||||
|
* This slice is defined by the index of the first evaluated argument and the number of processed elements.
|
||||||
|
*/
|
||||||
struct ParallelApplyAssignment
|
struct ParallelApplyAssignment
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
int size;
|
int size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Data useful for a parallel apply (map).
|
||||||
|
*
|
||||||
|
* A parallel apply needs at least the functor to apply to every element of the table, and the table itself,
|
||||||
|
* whereas it can be set later with the function init(). Master rank is also needed, to send it informations and
|
||||||
|
* receive informations from it, inside the functors (the job knows these values, but the functors don't). The
|
||||||
|
* size of a packet can be tuned here.
|
||||||
|
*
|
||||||
|
* Internal attributes contain:
|
||||||
|
* - (useful for master) the index of the next element to be evaluated.
|
||||||
|
* - (useful for master) a map containing links between MPI ranks and slices of the table which the worker with
|
||||||
|
* this rank has evaluated. Without this map, when receiving results from a worker, the master couldn't be
|
||||||
|
* able to replace the right elements in the table.
|
||||||
|
*
|
||||||
|
* @ingroup Parallel
|
||||||
|
*/
|
||||||
template<class EOT>
|
template<class EOT>
|
||||||
struct ParallelApplyData
|
struct ParallelApplyData
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief Ctor for Parallel apply (map) data.
|
||||||
|
*
|
||||||
|
* @param _proc The functor to apply on each element in the table
|
||||||
|
* @param _masterRank The MPI rank of the master
|
||||||
|
* @param _packetSize The number of elements on which the function will be applied by the worker, at a time.
|
||||||
|
* @param _pop The table to apply. If this value is NULL, user will have to call init() before launching the
|
||||||
|
* job.
|
||||||
|
*/
|
||||||
ParallelApplyData(
|
ParallelApplyData(
|
||||||
eoUF<EOT&, void> & _proc,
|
eoUF<EOT&, void> & _proc,
|
||||||
int _masterRank,
|
int _masterRank,
|
||||||
// long _maxTime = 0,
|
|
||||||
int _packetSize,
|
int _packetSize,
|
||||||
std::vector<EOT> * _pop = 0
|
std::vector<EOT> * _pop = 0
|
||||||
) :
|
) :
|
||||||
|
|
@ -39,6 +111,9 @@ namespace eo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reinitializes the data for a new table to evaluate.
|
||||||
|
*/
|
||||||
void init( std::vector<EOT>& _pop )
|
void init( std::vector<EOT>& _pop )
|
||||||
{
|
{
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
@ -52,11 +127,12 @@ namespace eo
|
||||||
return *_data;
|
return *_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All elements are public since functors will often use them.
|
||||||
std::vector<EOT> * _data;
|
std::vector<EOT> * _data;
|
||||||
eoUF<EOT&, void> & func;
|
eoUF<EOT&, void> & func;
|
||||||
int index;
|
int index;
|
||||||
int size;
|
int size;
|
||||||
std::map< int /* worker rank */, ParallelApplyAssignment /* min indexes in vector */> assignedTasks;
|
std::map< int /* worker rank */, ParallelApplyAssignment /* last assignment */> assignedTasks;
|
||||||
int packetSize;
|
int packetSize;
|
||||||
std::vector<EOT> tempArray;
|
std::vector<EOT> tempArray;
|
||||||
|
|
||||||
|
|
@ -64,6 +140,15 @@ namespace eo
|
||||||
bmpi::communicator& comm;
|
bmpi::communicator& comm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send task functor implementation for the parallel apply (map) job.
|
||||||
|
*
|
||||||
|
* Master side: Sends a slice of the table to evaluate to the worker.
|
||||||
|
*
|
||||||
|
* Implementation details:
|
||||||
|
* Finds the next slice of data to send to the worker, sends first the size and then the data, and memorizes
|
||||||
|
* that this slice has been distributed to the worker, then updates the next position of element to evaluate.
|
||||||
|
*/
|
||||||
template< class EOT >
|
template< class EOT >
|
||||||
class SendTaskParallelApply : public SendTaskFunction< ParallelApplyData<EOT> >
|
class SendTaskParallelApply : public SendTaskFunction< ParallelApplyData<EOT> >
|
||||||
{
|
{
|
||||||
|
|
@ -100,6 +185,11 @@ namespace eo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle response functor implementation for the parallel apply (map) job.
|
||||||
|
*
|
||||||
|
* Master side: Replaces the slice of data attributed to the worker in the table.
|
||||||
|
*/
|
||||||
template< class EOT >
|
template< class EOT >
|
||||||
class HandleResponseParallelApply : public HandleResponseFunction< ParallelApplyData<EOT> >
|
class HandleResponseParallelApply : public HandleResponseFunction< ParallelApplyData<EOT> >
|
||||||
{
|
{
|
||||||
|
|
@ -117,6 +207,14 @@ namespace eo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process task functor implementation for the parallel apply (map) job.
|
||||||
|
*
|
||||||
|
* Worker side: apply the function to the given slice of data.
|
||||||
|
*
|
||||||
|
* Implementation details: retrieves the number of elements to evaluate, retrieves them, applies the function
|
||||||
|
* and then returns the results.
|
||||||
|
*/
|
||||||
template< class EOT >
|
template< class EOT >
|
||||||
class ProcessTaskParallelApply : public ProcessTaskFunction< ParallelApplyData<EOT> >
|
class ProcessTaskParallelApply : public ProcessTaskFunction< ParallelApplyData<EOT> >
|
||||||
{
|
{
|
||||||
|
|
@ -145,6 +243,12 @@ namespace eo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Is finished functor implementation for the parallel apply (map) job.
|
||||||
|
*
|
||||||
|
* Master side: returns true if and only if the whole table has been evaluated. The job is also terminated only
|
||||||
|
* when the whole table has been evaluated.
|
||||||
|
*/
|
||||||
template< class EOT >
|
template< class EOT >
|
||||||
class IsFinishedParallelApply : public IsFinishedFunction< ParallelApplyData<EOT> >
|
class IsFinishedParallelApply : public IsFinishedFunction< ParallelApplyData<EOT> >
|
||||||
{
|
{
|
||||||
|
|
@ -162,6 +266,14 @@ namespace eo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Store containing all the datas and the functors for the parallel apply (map) job.
|
||||||
|
*
|
||||||
|
* User can tune functors when constructing the object. For each functor which is not given, a default one is
|
||||||
|
* generated.
|
||||||
|
*
|
||||||
|
* @ingroup Parallel
|
||||||
|
*/
|
||||||
template< class EOT >
|
template< class EOT >
|
||||||
struct ParallelApplyStore : public JobStore< ParallelApplyData<EOT> >
|
struct ParallelApplyStore : public JobStore< ParallelApplyData<EOT> >
|
||||||
{
|
{
|
||||||
|
|
@ -170,6 +282,17 @@ namespace eo
|
||||||
using JobStore< ParallelApplyData<EOT> >::_ptf;
|
using JobStore< ParallelApplyData<EOT> >::_ptf;
|
||||||
using JobStore< ParallelApplyData<EOT> >::_iff;
|
using JobStore< ParallelApplyData<EOT> >::_iff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Main constructor for the parallel apply (map) job.
|
||||||
|
*
|
||||||
|
* @param _proc The procedure to apply to each element of the table.
|
||||||
|
* @param _masterRank The rank of the master process.
|
||||||
|
* @param _packetSize The number of elements of the table to be evaluated at a time, by the worker.
|
||||||
|
* @param stpa Pointer to Send Task parallel apply functor descendant. If null, a default one is used.
|
||||||
|
* @param hrpa Pointer to Handle Response parallel apply functor descendant. If null, a default one is used.
|
||||||
|
* @param ptpa Pointer to Process Task parallel apply functor descendant. If null, a default one is used.
|
||||||
|
* @param ifpa Pointer to Is Finished parallel apply functor descendant. If null, a default one is used.
|
||||||
|
*/
|
||||||
ParallelApplyStore(
|
ParallelApplyStore(
|
||||||
eoUF<EOT&, void> & _proc,
|
eoUF<EOT&, void> & _proc,
|
||||||
int _masterRank,
|
int _masterRank,
|
||||||
|
|
@ -210,12 +333,17 @@ namespace eo
|
||||||
|
|
||||||
ParallelApplyData<EOT>* data() { return &_data; }
|
ParallelApplyData<EOT>* data() { return &_data; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reinits the store with a new table to evaluate.
|
||||||
|
*
|
||||||
|
* @param _pop The table of elements to be evaluated.
|
||||||
|
*/
|
||||||
void data( std::vector<EOT>& _pop )
|
void data( std::vector<EOT>& _pop )
|
||||||
{
|
{
|
||||||
_data.init( _pop );
|
_data.init( _pop );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ParallelApplyStore()
|
virtual ~ParallelApplyStore() // for inheritance purposes only
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,8 +351,15 @@ namespace eo
|
||||||
ParallelApplyData<EOT> _data;
|
ParallelApplyData<EOT> _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO commentaire : impossible de faire un typedef sur un template sans passer
|
/**
|
||||||
// par un traits => complique la tâche de l'utilisateur pour rien.
|
* @brief Parallel apply job. Present for convenience only.
|
||||||
|
*
|
||||||
|
* A typedef wouldn't have been working, as typedef on templates don't work in C++. Traits would be a
|
||||||
|
* disgraceful overload for the user.
|
||||||
|
*
|
||||||
|
* @ingroup Parallel
|
||||||
|
* @see eoParallelApply.h
|
||||||
|
*/
|
||||||
template< typename EOT >
|
template< typename EOT >
|
||||||
class ParallelApply : public MultiJob< ParallelApplyData<EOT> >
|
class ParallelApply : public MultiJob< ParallelApplyData<EOT> >
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,24 @@
|
||||||
|
/*
|
||||||
|
(c) Thales group, 2012
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation;
|
||||||
|
version 2 of the License.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Contact: http://eodev.sourceforge.net
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||||
|
*/
|
||||||
# ifndef __EO_TERMINATE_H__
|
# ifndef __EO_TERMINATE_H__
|
||||||
# define __EO_TERMINATE_H__
|
# define __EO_TERMINATE_H__
|
||||||
|
|
||||||
|
|
@ -7,6 +28,14 @@ namespace eo
|
||||||
{
|
{
|
||||||
namespace mpi
|
namespace mpi
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @ingroup Parallel
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send task functor which does nothing.
|
||||||
|
*/
|
||||||
struct DummySendTaskFunction : public SendTaskFunction<void>
|
struct DummySendTaskFunction : public SendTaskFunction<void>
|
||||||
{
|
{
|
||||||
void operator()( int _ )
|
void operator()( int _ )
|
||||||
|
|
@ -15,6 +44,9 @@ namespace eo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle response functor which does nothing.
|
||||||
|
*/
|
||||||
struct DummyHandleResponseFunction : public HandleResponseFunction<void>
|
struct DummyHandleResponseFunction : public HandleResponseFunction<void>
|
||||||
{
|
{
|
||||||
void operator()( int _ )
|
void operator()( int _ )
|
||||||
|
|
@ -23,6 +55,9 @@ namespace eo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process task functor which does nothing.
|
||||||
|
*/
|
||||||
struct DummyProcessTaskFunction : public ProcessTaskFunction<void>
|
struct DummyProcessTaskFunction : public ProcessTaskFunction<void>
|
||||||
{
|
{
|
||||||
void operator()()
|
void operator()()
|
||||||
|
|
@ -31,6 +66,9 @@ namespace eo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Is finished functor which returns true everytime.
|
||||||
|
*/
|
||||||
struct DummyIsFinishedFunction : public IsFinishedFunction<void>
|
struct DummyIsFinishedFunction : public IsFinishedFunction<void>
|
||||||
{
|
{
|
||||||
bool operator()()
|
bool operator()()
|
||||||
|
|
@ -39,6 +77,9 @@ namespace eo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Job store containing all dummy functors and containing no data.
|
||||||
|
*/
|
||||||
struct DummyJobStore : public JobStore<void>
|
struct DummyJobStore : public JobStore<void>
|
||||||
{
|
{
|
||||||
using JobStore<void>::_stf;
|
using JobStore<void>::_stf;
|
||||||
|
|
@ -61,11 +102,20 @@ namespace eo
|
||||||
void* data() { return 0; }
|
void* data() { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Job to run after a Multi Job, so as to indicate that every workers should terminate.
|
||||||
|
*/
|
||||||
struct EmptyJob : public OneShotJob<void>
|
struct EmptyJob : public OneShotJob<void>
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief Main EmptyJob ctor
|
||||||
|
*
|
||||||
|
* @param algo Assignment (scheduling) algorithm used.
|
||||||
|
* @param masterRank The rank of the master process.
|
||||||
|
*/
|
||||||
EmptyJob( AssignmentAlgorithm& algo, int masterRank ) :
|
EmptyJob( AssignmentAlgorithm& algo, int masterRank ) :
|
||||||
OneShotJob<void>( algo, masterRank, *(new DummyJobStore) )
|
OneShotJob<void>( algo, masterRank, *(new DummyJobStore) )
|
||||||
// FIXME memory leak => will be corrected by using const correctness
|
// FIXME memory leak, meaningless but present
|
||||||
{
|
{
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
@ -79,6 +129,10 @@ namespace eo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Reference in a new issue