Policies system using tag-dispatching method (again)

git-svn-id: svn://scm.gforge.inria.fr/svnroot/paradiseo@2723 331e1502-861f-0410-8da2-ba01fb791d7f
This commit is contained in:
quemy 2012-08-24 16:55:23 +00:00
commit a7cc3dab81
10 changed files with 266 additions and 66 deletions

View file

@ -1,5 +1,5 @@
template<template <class> class EOAlgo, class EOT>
void paradiseo::smp::MWModel<EOAlgo,EOT>::operator()(eoPop<EOT>& _pop, const eoEasyEA_tag&)
template<template <class> class EOAlgo, class EOT, class Policy>
void paradiseo::smp::MWModel<EOAlgo,EOT,Policy>::operator()(eoPop<EOT>& _pop, const eoEasyEA_tag&)
{
if (this->isFirstCall)

View file

@ -1,5 +1,5 @@
template<template <class> class EOAlgo, class EOT>
void paradiseo::smp::MWModel<EOAlgo,EOT>::operator()(eoPop<EOT>& _pop, const eoEasyPSO_tag&)
template<template <class> class EOAlgo, class EOT, class Policy>
void paradiseo::smp::MWModel<EOAlgo,EOT,Policy>::operator()(eoPop<EOT>& _pop, const eoEasyPSO_tag&)
{
try
{

View file

@ -1,5 +1,5 @@
template<template <class> class EOAlgo, class EOT>
void paradiseo::smp::MWModel<EOAlgo,EOT>::operator()(eoPop<EOT>& _pop, const eoSyncEasyPSO_tag&)
template<template <class> class EOAlgo, class EOT, class Policy>
void paradiseo::smp::MWModel<EOAlgo,EOT,Policy>::operator()(eoPop<EOT>& _pop, const eoSyncEasyPSO_tag&)
{
try
{

View file

@ -27,44 +27,44 @@ ParadisEO WebSite : http://paradiseo.gforge.inria.fr
Contact: paradiseo-help@lists.gforge.inria.fr
*/
template<template <class> class EOAlgo, class EOT>
template<template <class> class EOAlgo, class EOT, class Policy>
template<class... Args>
paradiseo::smp::MWModel<EOAlgo,EOT>::MWModel (unsigned workersNb, Args&... args) :
paradiseo::smp::MWModel<EOAlgo,EOT,Policy>::MWModel (unsigned workersNb, Args&... args) :
EOAlgo<EOT>(args...),
scheduler(workersNb)
{ assert(workersNb > 0); }
template<template <class> class EOAlgo, class EOT>
template<template <class> class EOAlgo, class EOT, class Policy>
template<class... Args>
paradiseo::smp::MWModel<EOAlgo,EOT>::MWModel (Args&... args) :
paradiseo::smp::MWModel<EOAlgo,EOT,Policy>::MWModel (Args&... args) :
MWModel(Thread::hardware_concurrency(), args...)
{}
template<template <class> class EOAlgo, class EOT>
paradiseo::smp::MWModel<EOAlgo,EOT>::~MWModel ()
template<template <class> class EOAlgo, class EOT, class Policy>
paradiseo::smp::MWModel<EOAlgo,EOT,Policy>::~MWModel ()
{}
template<template <class> class EOAlgo, class EOT>
void paradiseo::smp::MWModel<EOAlgo,EOT>::apply(eoUF<EOT&, void>& func, eoPop<EOT>& pop)
template<template <class> class EOAlgo, class EOT, class Policy>
void paradiseo::smp::MWModel<EOAlgo,EOT,Policy>::apply(eoUF<EOT&, void>& func, eoPop<EOT>& pop)
{
scheduler(func, pop);
}
template<template <class> class EOAlgo, class EOT>
void paradiseo::smp::MWModel<EOAlgo,EOT>::evaluate(eoPop<EOT>& pop)
template<template <class> class EOAlgo, class EOT, class Policy>
void paradiseo::smp::MWModel<EOAlgo,EOT,Policy>::evaluate(eoPop<EOT>& pop)
{
scheduler(this->eval, pop);
}
template<template <class> class EOAlgo, class EOT>
void paradiseo::smp::MWModel<EOAlgo,EOT>::operator()(eoPop<EOT>& pop)
template<template <class> class EOAlgo, class EOT, class Policy>
void paradiseo::smp::MWModel<EOAlgo,EOT,Policy>::operator()(eoPop<EOT>& pop)
{
// Call the tag dispatcher
operator()(pop,typename traits<EOAlgo,EOT>::type());
}
template<template <class> class EOAlgo, class EOT>
void paradiseo::smp::MWModel<EOAlgo,EOT>::operator()(eoPop<EOT>& pop, const error_tag&)
template<template <class> class EOAlgo, class EOT, class Policy>
void paradiseo::smp::MWModel<EOAlgo,EOT,Policy>::operator()(eoPop<EOT>& pop, const error_tag&)
{
throw std::runtime_error("This is not a valid algorithm");
}

View file

@ -33,8 +33,8 @@ Contact: paradiseo-help@lists.gforge.inria.fr
#include <cassert>
#include <scheduler.h>
#include <tagDispatching.h>
#include <algoDispatching.h>
#include <policiesDispatching.h>
#include <eo>
@ -52,7 +52,7 @@ The MW Model wraps any algorithm in order to apply it on several populations.
@see smp::Worker, smp::Thread
*/
template<template <class> class EOAlgo, class EOT>
template<template <class> class EOAlgo, class EOT, class Policy = LinearPolicy>
class MWModel : public EOAlgo<EOT>
{
public:
@ -114,7 +114,7 @@ protected:
void operator()(eoPop<EOT>& pop,const error_tag&);
std::vector<Thread*> workers;
Scheduler<EOT> scheduler;
Scheduler<EOT,Policy> scheduler;
};
#include <MWModel.cpp>

View file

@ -0,0 +1,73 @@
/*
<algoDispatching.h>
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
Alexandre Quemy
This software is governed by the CeCILL license under French law and
abiding by the rules of distribution of free software. You can ue,
modify and/ or redistribute the software under the terms of the CeCILL
license as circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info".
In this respect, the user's attention is drawn to the risks associated
with loading, using, modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean that it is complicated to manipulate, and that also
therefore means that it is reserved for developers and experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or
data to be ensured and, more generally, to use and operate it in the
same conditions as regards security.
The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms.
ParadisEO WebSite : http://paradiseo.gforge.inria.fr
Contact: paradiseo-help@lists.gforge.inria.fr
*/
#ifndef ALGO_D_H_
#define ALGO_D_H_
#include <eo>
namespace paradiseo
{
namespace smp
{
/** Algo Dispatching
* The Algo Dispatching enable to choose the algorithm to call at compile time by tag-dispatching method
**/
// Main algorithms tags
struct error_tag {};
struct eoEasyEA_tag {};
struct eoEasyPSO_tag {};
struct eoSyncEasyPSO_tag {};
template<template <class> class A, class B>
struct traits {
typedef error_tag type;
};
template<class B>
struct traits<eoEasyEA,B> {
typedef eoEasyEA_tag type;
};
template<class B>
struct traits<eoEasyPSO,B> {
typedef eoEasyPSO_tag type;
};
template<class B>
struct traits<eoSyncEasyPSO,B> {
typedef eoSyncEasyPSO_tag type;
};
}
}
#endif

View file

@ -0,0 +1,61 @@
/*
<policiesDispatching.h>
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
Alexandre Quemy
This software is governed by the CeCILL license under French law and
abiding by the rules of distribution of free software. You can ue,
modify and/ or redistribute the software under the terms of the CeCILL
license as circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info".
In this respect, the user's attention is drawn to the risks associated
with loading, using, modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean that it is complicated to manipulate, and that also
therefore means that it is reserved for developers and experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or
data to be ensured and, more generally, to use and operate it in the
same conditions as regards security.
The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms.
ParadisEO WebSite : http://paradiseo.gforge.inria.fr
Contact: paradiseo-help@lists.gforge.inria.fr
*/
#ifndef POLICIES_D_H_
#define POLICIES_D_H_
#include <eo>
namespace paradiseo
{
namespace smp
{
/** Policies Dispatching
* The Policies Dispatching enable to choose the policy to call at compile time by tag-dispatching method
**/
struct LinearPolicy {};
struct ProgressivePolicy {};
template<class B>
struct policyTraits {
typedef LinearPolicy type;
};
template<>
struct policyTraits<ProgressivePolicy> {
typedef ProgressivePolicy type;
};
}
}
#endif

View file

@ -27,29 +27,70 @@ ParadisEO WebSite : http://paradiseo.gforge.inria.fr
Contact: paradiseo-help@lists.gforge.inria.fr
*/
template<class EOT>
paradiseo::smp::Scheduler<EOT>::Scheduler(unsigned workersNb) :
#include <typeinfo>
template<class EOT, class Policy>
paradiseo::smp::Scheduler<EOT,Policy>::Scheduler(unsigned workersNb) :
workers(workersNb),
popPackages(workersNb),
done(false),
planning(workersNb),
idWaitingThread(-1)
m(workersNb)
{ }
template<class EOT>
paradiseo::smp::Scheduler<EOT>::~Scheduler()
template<class EOT, class Policy>
paradiseo::smp::Scheduler<EOT,Policy>::~Scheduler()
{ }
template<class EOT>
void paradiseo::smp::Scheduler<EOT>::operator()(eoUF<EOT&, void>& func, eoPop<EOT>& pop)
template<class EOT, class Policy>
void paradiseo::smp::Scheduler<EOT,Policy>::operator()(eoUF<EOT&, void>& func, eoPop<EOT>& pop)
{
// Call the tag dispatcher
operator()(func, pop,typename policyTraits<Policy>::type());
}
template<class EOT, class Policy>
void paradiseo::smp::Scheduler<EOT,Policy>::operator()(eoUF<EOT&, void>& func, eoPop<EOT>& pop, const LinearPolicy&)
{
// Determine number of packages according to the number of workers
unsigned nbPackages = workers.size();
// Fill packages
unsigned nbIndi = pop.size() / nbPackages;
unsigned remaining = pop.size() % nbPackages;
unsigned indice = 0;
for(unsigned i = 0; i < nbPackages; i++)
{
popPackages[i].clear();
for(unsigned j = 0; j < nbIndi; j++)
{
popPackages[i].push_back(&pop[i*nbIndi+j]);
indice = i*nbIndi+j;
}
}
for(unsigned i = 0; i < remaining; i++)
popPackages[i].push_back(&pop[indice+i+1]);
// Starting threads
for(unsigned i = 0; i < workers.size(); i++)
workers[i].start(&Scheduler<EOT,Policy>::applyLinearPolicy, this, std::ref(func), std::ref(popPackages[i]));
// Wait the end of tasks
for(unsigned i = 0; i < workers.size(); i++)
workers[i].join();
}
template<class EOT, class Policy>
void paradiseo::smp::Scheduler<EOT,Policy>::operator()(eoUF<EOT&, void>& func, eoPop<EOT>& pop, const ProgressivePolicy&)
{
done = false;
idWaitingThread = -1;
for(unsigned i = 0; i < workers.size(); i++)
{
planning[i] = 2;
workers[i].start(&Scheduler<EOT>::apply, this, std::ref(func), std::ref(popPackages[i]), i);
workers[i].start(&Scheduler<EOT,Policy>::applyProgressivePolicy, this, std::ref(func), std::ref(popPackages[i]), i);
}
unsigned counter = 0;
@ -57,41 +98,51 @@ void paradiseo::smp::Scheduler<EOT>::operator()(eoUF<EOT&, void>& func, eoPop<EO
while(counter < pop.size())
{
std::unique_lock<std::mutex> lock(m);
cvt.wait(lock, [this]() -> bool {return (int)idWaitingThread != -1;});
j = 0;
while (j < planning[idWaitingThread] && counter < pop.size())
for(unsigned i = 0; i < workers.size(); i++)
{
popPackages[idWaitingThread].push_back(&pop[counter]);
counter++;
j++;
if(popPackages[i].empty() && counter < pop.size())
{
j = 0;
std::unique_lock<std::mutex> lock(m[i]);
while (j < planning[i] && counter < pop.size())
{
//std::cout << counter << std::endl;
popPackages[i].push_back(&pop[counter]);
counter++;
j++;
}
planning[i] *= 2;
}
}
planning[idWaitingThread] *= 2;
idWaitingThread = -1;
cv.notify_one();
/* A nanosleep can increase performances by 10% but
as it is not supported by Fedora atm, I deactivate it. */
//std::this_thread::sleep_for(std::chrono::nanoseconds(10));
}
done = true;
idWaitingThread = -1;
cv.notify_all();
for(unsigned i = 0; i < workers.size(); i++)
workers[i].join();
}
template<class EOT>
void paradiseo::smp::Scheduler<EOT>::apply(eoUF<EOT&, void>& func, std::vector<EOT*>& pop, int id)
template<class EOT, class Policy>
void paradiseo::smp::Scheduler<EOT,Policy>::applyLinearPolicy(eoUF<EOT&, void>& func, std::vector<EOT*>& pop)
{
for(unsigned i = 0; i < pop.size(); i++)
func(*pop[i]);
}
template<class EOT, class Policy>
void paradiseo::smp::Scheduler<EOT,Policy>::applyProgressivePolicy(eoUF<EOT&, void>& func, std::vector<EOT*>& pop, int id)
{
while(!done || !pop.empty())
{
for(unsigned i = 0; i < pop.size(); i++)
std::unique_lock<std::mutex> lock(m[id]);
for(unsigned i = 0; i < pop.size(); i++) {
//std::cout << "." << id << "." << std::endl;
func(*pop[i]);
}
pop.clear();
std::unique_lock<std::mutex> lock(m);
idWaitingThread = id;
// We notify the scheduler we finished the package
cvt.notify_one();
// We wait for a new package
cv.wait(lock, [this]() -> bool {return (int)idWaitingThread == -1 || (bool)done;});
lock.unlock();
}
}

View file

@ -34,13 +34,14 @@ Contact: paradiseo-help@lists.gforge.inria.fr
#include <vector>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <thread.h>
#include <policiesDispatching.h>
#include <eoEvalFunc.h>
#include <eoPop.h>
namespace paradiseo
{
namespace smp
@ -48,7 +49,7 @@ namespace smp
/**
A scheduler class
*/
template<class EOT>
template<class EOT, class Policy = LinearPolicy>
class Scheduler
{
public:
@ -69,15 +70,32 @@ public:
* @param pop reference to the population
*/
void operator()(eoUF<EOT&, void>& func, eoPop<EOT>& pop);
protected:
/**
* Perform scheduling with a linear policy
*/
void operator()(eoUF<EOT&, void>& func, eoPop<EOT>& pop, const LinearPolicy&);
/**
* Perform scheduling with a linear policy
*/
void operator()(eoUF<EOT&, void>& func, eoPop<EOT>& pop, const ProgressivePolicy&);
/**
* Apply an unary functor on a sub-group of population
* @param func unary functor
* @param pop reference to the sub-group
*/
void applyLinearPolicy(eoUF<EOT&, void>& func, std::vector<EOT*>& pop);
/**
* Apply an unary functor on a sub-group of population
* @param func unary functor
* @param pop reference to the sub-group
* @param id id of the thread
*/
void apply(eoUF<EOT&, void>& func, std::vector<EOT*>& pop, int id);
void applyProgressivePolicy(eoUF<EOT&, void>& func, std::vector<EOT*>& pop, int id);
/**
* Create sub-groups with similar size from a population.
@ -87,13 +105,11 @@ protected:
std::vector<Thread> workers;
std::vector<std::vector<EOT*>> popPackages;
std::mutex m;
std::atomic<bool> done;
std::vector<unsigned> planning;
std::atomic<int> idWaitingThread;
std::condition_variable cv;
std::condition_variable cvt;
std::vector<std::atomic<int>> isWorking;
std::vector<std::mutex> m;
};
#include <scheduler.cpp>

View file

@ -25,7 +25,6 @@ int main(void)
int nbWorkers = 4;
Scheduler<Indi> sched(nbWorkers);
sched(plainEval, pop);