Commit ba13f792 authored by Pierre Kraemer's avatar Pierre Kraemer

remove deprecated parallel_foreach

parent a5c5ec19
...@@ -97,8 +97,8 @@ target_link_libraries( tuto_histo ...@@ -97,8 +97,8 @@ target_link_libraries( tuto_histo
# exemple: BOOST_LIBS(boost_lib_lists "boost_thread-mt;boost_iostreams-mt") # exemple: BOOST_LIBS(boost_lib_lists "boost_thread-mt;boost_iostreams-mt")
#BOOST_LIBS(boost_lib_lists "boost_thread-mt") #BOOST_LIBS(boost_lib_lists "boost_thread-mt")
QT4_WRAP_CPP(tuto_mt_moc tuto_mt.h) #QT4_WRAP_CPP(tuto_mt_moc tuto_mt.h)
add_executable( tuto_mt tuto_mt.cpp ${tuto_mt_moc}) #add_executable( tuto_mt tuto_mt.cpp ${tuto_mt_moc})
target_link_libraries( tuto_mt #target_link_libraries( tuto_mt
${CGoGN_LIBS_D} ${CGoGN_EXT_LIBS} ${Boost_THREAD_LIBRARY}) # ${CGoGN_LIBS_D} ${CGoGN_EXT_LIBS} ${Boost_THREAD_LIBRARY})
...@@ -39,8 +39,6 @@ ...@@ -39,8 +39,6 @@
//#include "Algo/Modelisation/polyhedron.h" //#include "Algo/Modelisation/polyhedron.h"
#include "Algo/Tiling/Surface/square.h" #include "Algo/Tiling/Surface/square.h"
#include "Algo/Parallel/parallel_foreach.h"
#include "Utils/cgognStream.h" #include "Utils/cgognStream.h"
#include "Utils/chrono.h" #include "Utils/chrono.h"
......
...@@ -43,6 +43,6 @@ TARGET_LINK_LIBRARIES( SCHNAppsD ...@@ -43,6 +43,6 @@ TARGET_LINK_LIBRARIES( SCHNAppsD
ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/Plugins PluginsD) ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/Plugins PluginsD)
IF(IS_DIRECTORY ${SCHNApps_ROOT_DIR}/../../Plugins) #IF(IS_DIRECTORY ${SCHNApps_ROOT_DIR}/../../Plugins)
ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/../../Plugins ExtPluginsD) # ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/../../Plugins ExtPluginsD)
ENDIF(IS_DIRECTORY ${SCHNApps_ROOT_DIR}/../../Plugins) #ENDIF(IS_DIRECTORY ${SCHNApps_ROOT_DIR}/../../Plugins)
...@@ -43,6 +43,6 @@ TARGET_LINK_LIBRARIES( SCHNApps ...@@ -43,6 +43,6 @@ TARGET_LINK_LIBRARIES( SCHNApps
ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/Plugins Plugins) ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/Plugins Plugins)
IF(IS_DIRECTORY ${SCHNApps_ROOT_DIR}/../../Plugins) #IF(IS_DIRECTORY ${SCHNApps_ROOT_DIR}/../../Plugins)
ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/../../Plugins ExtPlugins) # ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/../../Plugins ExtPlugins)
ENDIF(IS_DIRECTORY ${SCHNApps_ROOT_DIR}/../../Plugins) #ENDIF(IS_DIRECTORY ${SCHNApps_ROOT_DIR}/../../Plugins)
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "Topology/generic/traversor/traversor2.h" #include "Topology/generic/traversor/traversor2.h"
#include "Topology/generic/traversor/traversorCell.h" #include "Topology/generic/traversor/traversorCell.h"
#include "Topology/generic/traversor/traversor3.h" #include "Topology/generic/traversor/traversor3.h"
#include "Algo/Parallel/parallel_foreach.h"
namespace CGoGN namespace CGoGN
{ {
......
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
#include "Topology/generic/traversor/traversorCell.h" #include "Topology/generic/traversor/traversorCell.h"
#include "Topology/generic/traversor/traversor2.h" #include "Topology/generic/traversor/traversor2.h"
#include "Algo/Parallel/parallel_foreach.h"
#include <cmath> #include <cmath>
namespace CGoGN namespace CGoGN
......
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg *
* *
* 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; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: http://cgogn.unistra.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#ifndef __PARALLEL_FOREACH__
#define __PARALLEL_FOREACH__
#include "Topology/generic/functor.h"
namespace CGoGN
{
namespace Algo
{
namespace Parallel
{
static unsigned int NBCORES = 0;
/// enum for optimalNbThreads parameter
enum NbParam {NB_HIGHMEMORY, NB_HIGHCOMPUTE, NB_VERYHIGHMEMORY};
/// size of buffers to store darts or indexes in each threads
const unsigned int SIZE_BUFFER_THREAD = 8192; // seems to be the best compromise
/**
* @return How much threads has you computer
*/
inline unsigned int nbThreads();
/**
* @param p can be NB_HIGHMEMORY (default) or NB_HIGHCOMPUTE or NB_VERYHIGHMEMORY
* @return Number of core in fact (work only with quad core with/without hyper threading)
*/
unsigned int optimalNbThreads( NbParam p=NB_HIGHMEMORY);
/**
* impossible to automatically determine the number of cores so ...
*/
void setNbCore(unsigned int nb);
//
//template <typename MAP>
//class Foreach
//{
// MAP& m_map;
//
// std::vector<FunctorMapThreaded<MAP>*> m_funcs;
//
// std::vector<Dart>* m_vd;
//
// unsigned int m_nbth;
//
//public:
// Foreach(MAP& map,unsigned int nbth);
//
// void clearFunctors();
//
// void addFunctor(FunctorMapThreaded<MAP>* funcPtr);
//
// template<typename T>
// T* getFunctor(unsigned int i);
//
// template <unsigned int ORBIT>
// void traverseCell(bool needMarkers = false, unsigned int currentThread = 0);
//
// template <unsigned int ORBIT>
// void traverseEachCell(bool needMarkers = false, unsigned int currentThread = 0);
//
// void traverseDart(bool needMarkers = false, unsigned int currentThread = 0);
//
// void traverseEachDart(bool needMarkers = false, unsigned int currentThread = 0);
//};
/**
* Traverse cells of a map in parallel. Use quick traversal, cell markers or dart markers if available !
* Use this version if you need to have acces to each functors after the traversal (to compute a sum or an average for example)
* @param map the map
* @param funcs the functors to apply (size of vector determine number of threads, and all functors must be of the same type)
* @param needMarkers set to yes if you want that each thread use different markers. Warning if set to false (default) do not use algo with thread id or markers !!
*/
template <typename MAP, unsigned int ORBIT>
void foreach_cell(MAP& map, std::vector<FunctorMapThreaded<MAP>*>& funcs, bool needMarkers = false);
/**
* Traverse cells of a map in parallel. Use quick traversal, cell markers or dart markers if available !
* Use this version if you do not need to keep functors
* @param map the map
* @param func the functor to apply
* @param nbth number of threads 0 for let the system choose
* @param needMarkers set to yes if you want that each thread use different markers. Warning if set to false (default) do not use algo with thread id or markers !!
*/
template <typename MAP, unsigned int ORBIT>
void foreach_cell(MAP& map, FunctorMapThreaded<MAP>& func, unsigned int nbth = 0, bool needMarkers = false);
/**
* Traverse cells of a map and apply differents functors in //
* Use this version if you need to have acces to each functors after the traversal (to compute a sum or an average for example)
* @param map the map
* @param funcs the functors to apply ( each functors can (should!) be here of different type)
* @param nbth number of threads
* @param needMarkers set to yes if you want that each thread use different markers. Warning if set to false (default) do not use algo with thread id or markers !!
*/
template <typename MAP, unsigned int ORBIT>
void foreach_cell_all_thread(MAP& map, std::vector<FunctorMapThreaded<MAP>*>& funcs, bool needMarkers = false);
/**
* Traverse darts of a map in parallel
* Use this version if you need to have acces to each functors after the traversal (to compute a sum or an average for example)
* @param map the map
* @param funcs the functors to apply (size of vector determine number of threads, and all functors must be of the same type)
* @param needMarkers set to yes if you want that each thread use different markers.Warning if set to false (default) do not use algo with thread id or markers !!
*/
template <typename MAP>
void foreach_dart(MAP& map, std::vector<FunctorMapThreaded<MAP>*>& funcs, unsigned int nbth, bool needMarkers = false);
/**
* Traverse darts of a map in parallel
* @param map the map
* @param funcs the functor
* @param nbth number of thread to use, 0 for let the system choose
* @param needMarkers set to yes if you want that each thread use different markers. Warning if set to false (default) do not use algo with thread id or markers !!
*/
template <typename MAP>
void foreach_dart(MAP& map, FunctorMapThreaded<MAP>& func, unsigned int nbth = 0, bool needMarkers = false);
/**
* Traverse all elements of an attribute container (attribute handler is placed in FunctorAttribThreaded)
* @param attr_cont the attribute container to traverse
* @param func the fonctors to use
*/
void foreach_attrib(AttributeContainer& attr_cont, std::vector<FunctorAttribThreaded*> funcs);
/**
* Traverse all elements of an attribute container (attribute handler is placed in FunctorAttribThreaded
* @param attr_cont the attribute container to traverse
* @param func the functor to use
* @param nbth number of thread to use for computation 0 for let the system choose
*/
void foreach_attrib(AttributeContainer& attr_cont, FunctorAttribThreaded& func, unsigned int nbth = 0);
/**
* Optimized version for // foreach with to pass (2 functors), with several loops
* Use this version if you need to keep functors
* @param map the map
* @param funcsFrontnBack nbth front pass functors followed by nbth back pass functors
* @param nbLoops number of loops to execute
* @param needMarkers set to yes if you want that each thread use different markers (markers are allocated if necessary)
*/
template <typename MAP, unsigned int CELL>
void foreach_cell2Pass(MAP& map, std::vector<FunctorMapThreaded<MAP>*>& funcsFrontnBack, unsigned int nbLoops, bool needMarkers = false);
/**
* Optimized version for // foreach with to pass (2 functors), with several loops
* Use this version if you do not need to keep functors
* @param map the map
* @param funcFront front pass functor
* @param funcBack back pass functor
* @param nbLoops number of loops to execute
* @param nbth number of threads to use
* @param needMarkers set to yes if you want that each thread use different markers (markers are allocated if necessary)
*/
template <typename MAP, unsigned int CELL>
void foreach_cell2Pass(MAP& map, FunctorMapThreaded<MAP>& funcFront, FunctorMapThreaded<MAP>& funcBack, unsigned int nbLoops, unsigned int nbth, bool needMarkers = false);
} // namespace Parallel
} // namespace Algo
} // namespace CGoGN
#include "Algo/Parallel/parallel_foreach.hpp"
#endif
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg *
* *
* 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; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: http://cgogn.unistra.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#include <boost/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <vector>
namespace CGoGN
{
namespace Algo
{
namespace Parallel
{
/// internal functor for boost call
class ThreadFunctionAttrib
{
protected:
std::vector<unsigned int>& m_ids;
boost::barrier& m_sync1;
boost::barrier& m_sync2;
bool& m_finished;
unsigned int m_id;
FunctorAttribThreaded* m_functor;
public:
ThreadFunctionAttrib(FunctorAttribThreaded* func, std::vector<unsigned int>& vid, boost::barrier& s1, boost::barrier& s2, bool& finished, unsigned int id):
m_ids(vid), m_sync1(s1), m_sync2(s2), m_finished(finished), m_id(id), m_functor(func)
{
}
ThreadFunctionAttrib(const ThreadFunctionAttrib& tf):
m_ids(tf.m_ids), m_sync1(tf.m_sync1), m_sync2(tf.m_sync2), m_finished(tf.m_finished), m_id(tf.m_id), m_functor(tf.m_functor){}
void operator()()
{
while (!m_finished)
{
for (std::vector<unsigned int>::const_iterator it = m_ids.begin(); it != m_ids.end(); ++it)
m_functor->run(*it,m_id);
m_sync1.wait();
m_sync2.wait();
}
}
};
/// internal functor for boost call
template<typename MAP>
class ThreadFunction
{
protected:
std::vector<Dart>& m_darts;
boost::barrier& m_sync1;
boost::barrier& m_sync2;
bool& m_finished;
unsigned int m_id;
FunctorMapThreaded<MAP>* m_functor;
public:
ThreadFunction(FunctorMapThreaded<MAP>* func, std::vector<Dart>& vd, boost::barrier& s1, boost::barrier& s2, bool& finished, unsigned int id):
m_darts(vd), m_sync1(s1), m_sync2(s2), m_finished(finished), m_id(id), m_functor(func)
{
}
ThreadFunction(const ThreadFunction<MAP>& tf):
m_darts(tf.m_darts), m_sync1(tf.m_sync1), m_sync2(tf.m_sync2), m_finished(tf.m_finished), m_id(tf.m_id), m_functor(tf.m_functor){}
void operator()()
{
while (!m_finished)
{
for (std::vector<Dart>::const_iterator it = m_darts.begin(); it != m_darts.end(); ++it)
m_functor->run(*it,m_id);
m_sync1.wait();
m_sync2.wait();
}
}
};
inline unsigned int nbThreads()
{
return boost::thread::hardware_concurrency();
}
inline unsigned int optimalNbThreads(NbParam p)
{
if (p==NB_HIGHCOMPUTE)
return nbThreads();
if (p==NB_VERYHIGHMEMORY)
return 2;
// NB_HIGHMEMORY
if (NBCORES != 0)
return NBCORES;
unsigned int nb = nbThreads();
if (nb>4)
return nb/2 ;
return nb;
}
template <typename MAP, unsigned int ORBIT>
void foreach_cell(MAP& map, FunctorMapThreaded<MAP>& func, unsigned int nbth, bool needMarkers)
{
if (nbth == 0)
nbth = optimalNbThreads();
std::vector<FunctorMapThreaded<MAP>*> funcs;
funcs.reserve(nbth);
FunctorMapThreaded<MAP>* ptr = func.duplicate();
bool shared = (ptr == NULL);
if (shared)
{
for (unsigned int i = 0; i < nbth; ++i)
funcs.push_back(&func);
}
else
{
funcs.push_back(ptr);
for (unsigned int i = 1; i < nbth; ++i)
funcs.push_back(func.duplicate());
}
foreach_cell<MAP,ORBIT>(map,funcs,needMarkers);
if (!shared)
for (unsigned int i = 0; i < nbth; ++i)
delete funcs[i];
}
template <typename MAP, unsigned int ORBIT>
void foreach_cell(MAP& map, std::vector<FunctorMapThreaded<MAP>*>& funcs, bool needMarkers)
{
unsigned int nbth = funcs.size();
std::vector<Dart>* vd = new std::vector<Dart>[nbth];
// nbth new functions, new thread (with good darts !)
for (unsigned int i = 0; i < nbth; ++i)
vd[i].reserve(SIZE_BUFFER_THREAD);
unsigned int nb=0;
TraversorCell<MAP, ORBIT> trav(map);
Cell<ORBIT> cell = trav.begin();
Cell<ORBIT> c_end = trav.end();
while ((cell.dart != c_end.dart) && (nb < nbth*SIZE_BUFFER_THREAD) )
{
vd[nb%nbth].push_back(cell.dart);
nb++;
cell = trav.next();
}
boost::barrier sync1(nbth+1);
boost::barrier sync2(nbth+1);
bool finished=false;
// launch threads
boost::thread** threads = new boost::thread*[nbth];
ThreadFunction<MAP>** tfs = new ThreadFunction<MAP>*[nbth];
for (unsigned int i = 0; i < nbth; ++i)
{
tfs[i] = new ThreadFunction<MAP>(funcs[i], vd[i],sync1,sync2, finished,1+i);
threads[i] = new boost::thread( boost::ref( *(tfs[i]) ) );
}
// and continue to traverse the map
std::vector<Dart>* tempo = new std::vector<Dart>[nbth];
for (unsigned int i = 0; i < nbth; ++i)
tempo[i].reserve(SIZE_BUFFER_THREAD);
while (cell.dart != c_end.dart)
{
for (unsigned int i = 0; i < nbth; ++i)
tempo[i].clear();
nb = 0;
while ((cell.dart != c_end.dart) && (nb < nbth*SIZE_BUFFER_THREAD) )
{
tempo[nb%nbth].push_back(cell);
nb++;
cell = trav.next();
}
sync1.wait(); // wait for all thread to finish its vector
for (unsigned int i = 0; i < nbth; ++i)
vd[i].swap(tempo[i]);
sync2.wait(); // everybody refilled then go
}
sync1.wait();// wait for all thread to finish its vector
finished = true; // say finsih to everyone
sync2.wait(); //wait to everybody to say finished !
//wait for all theads to be finished
for (unsigned int i = 0; i < nbth; ++i)
{
threads[i]->join();
delete threads[i];
delete tfs[i];
}
delete[] tfs;
delete[] threads;
delete[] vd;
delete[] tempo;
}
template <typename MAP>
void foreach_dart(MAP& map, FunctorMapThreaded<MAP>& func, unsigned int nbth, bool needMarkers)
{
if (nbth == 0)
nbth = optimalNbThreads();
std::vector<FunctorMapThreaded<MAP>*> funcs;
funcs.reserve(nbth);
FunctorMapThreaded<MAP>* ptr = func.duplicate();
bool shared = (ptr == NULL);
if (shared)
{
for (unsigned int i = 0; i < nbth; ++i)
funcs.push_back(&func);
}
else
{
funcs.push_back(ptr);
for (unsigned int i = 1; i < nbth; ++i)
funcs.push_back(func.duplicate());
}
foreach_dart<MAP>(map,funcs,needMarkers);
if (!shared)
for (unsigned int i = 0; i < nbth; ++i)
delete funcs[i];
}
template <typename MAP>
void foreach_dart(MAP& map, std::vector<FunctorMapThreaded<MAP>*> funcs, bool needMarkers)
{
unsigned int nbth = funcs.size();
std::vector<Dart>* vd = new std::vector<Dart>[nbth];
boost::thread** threads = new boost::thread*[nbth];
Dart d = map.begin();
// nbth new functions, new thread (with good darts !)
for (unsigned int i = 0; i < nbth; ++i)
vd[i].reserve(SIZE_BUFFER_THREAD);
// fill each vd buffers with 4096 darts
unsigned int nb = 0;
while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) )
{
vd[nb%nbth].push_back(d);
nb++;
map.next(d);
}
boost::barrier sync1(nbth+1);
boost::barrier sync2(nbth+1);
bool finished = false;
// lauch threads
if (needMarkers)
{
unsigned int nbth_prec = map.getNbThreadMarkers();
if (nbth_prec < nbth+1)
map.addThreadMarker(nbth+1-nbth_prec);
}
for (unsigned int i = 0; i < nbth; ++i)
{
threads[i] = new boost::thread(ThreadFunction<MAP>(funcs[i], vd[i],sync1,sync2, finished,1+i));
}
// and continue to traverse the map
std::vector<Dart>* tempo = new std::vector<Dart>[nbth];
for (unsigned int i = 0; i < nbth; ++i)
tempo[i].reserve(SIZE_BUFFER_THREAD);
while (d != map.end())
{
for (unsigned int i = 0; i < nbth; ++i)
tempo[i].clear();
unsigned int nb =0;
while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) )
{
tempo[nb%nbth].push_back(d);
nb++;
map.next(d);
}
sync1.wait();
for (unsigned int i = 0; i < nbth; ++i)
vd[i].swap(tempo[i]);
sync2.wait();
}
sync1.wait();
finished = true;
sync2.wait();
//wait for all theads to be finished
for (unsigned int i = 0; i < nbth; ++i)
{
threads[i]->join();
delete threads[i];
}
delete vd;
delete threads;
delete tempo;
}
// TODO same modification for transparent usage of dart marker / cell marker / quick traversal ??
template <typename MAP, unsigned int CELL>
void foreach_cell2Pass(MAP& map, std::vector<FunctorMapThreaded<MAP>*>& funcsFrontnBack, unsigned int nbLoops, bool needMarkers)
{
unsigned int nbth = funcsFrontnBack.size()/2;
std::vector<Dart>* vd = new std::vector<Dart>[2*nbth];
for (unsigned int i = 0; i < nbth; ++i)
vd[i].reserve(SIZE_BUFFER_THREAD);
boost::thread** threadsAB = new boost::thread*[2*nbth];
if (needMarkers)
{
// ensure that there is enough threads