/******************************************************************************* * 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 #include #include namespace CGoGN { namespace Algo { namespace Parallel { /** * */ template class ThreadFunction { protected: std::vector& m_darts; boost::barrier& m_sync1; boost::barrier& m_sync2; bool& m_finished; FunctorMapThreaded* m_functor; public: ThreadFunction(FunctorMapThreaded& func, std::vector& 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_functor = func.duplicate(id); } ThreadFunction(const ThreadFunction& tf): m_darts(tf.m_darts), m_sync1(tf.m_sync1), m_sync2(tf.m_sync2), m_finished(tf.m_finished), m_functor(tf.m_functor){} void operator()() { while (!m_finished) { for (std::vector::const_iterator it = m_darts.begin(); it != m_darts.end(); ++it) m_functor->operator()(*it); m_sync1.wait(); m_sync2.wait(); } } void clean() { delete m_functor; } }; template class ThreadFunctionResult { protected: std::vector& m_darts; boost::barrier& m_sync1; boost::barrier& m_sync2; bool& m_finished; FunctorMapThreadedResult* m_functor; T& m_result; public: ThreadFunctionResult(FunctorMapThreadedResult& func, std::vector& vd, boost::barrier& s1, boost::barrier& s2, bool& finished, unsigned int id, T& result): m_darts(vd), m_sync1(s1), m_sync2(s2), m_finished(finished), m_result(result) { m_functor = reinterpret_cast< FunctorMapThreadedResult* >(func.duplicate(id)); } ThreadFunctionResult(const ThreadFunctionResult& tf): m_darts(tf.m_darts), m_sync1(tf.m_sync1), m_sync2(tf.m_sync2), m_finished(tf.m_finished), m_functor(tf.m_functor), m_result(tf.m_result){} void operator()() { while (!m_finished) { for (std::vector::const_iterator it = m_darts.begin(); it != m_darts.end(); ++it) m_functor->operator()(*it); m_sync1.wait(); m_sync2.wait(); } m_result = this->m_functor->getResult(); } void clean() { delete m_functor; } }; template void foreach_orbit(typename PFP::MAP& map, unsigned int orbit, FunctorMapThreaded& func, unsigned int nbth, unsigned int szbuff, bool needMarkers, const FunctorSelect& good) { std::vector* vd = new std::vector[nbth]; boost::thread** threads = new boost::thread*[nbth]; DartMarker dm(map); Dart d=map.begin(); // nbth new functions, new thread (with good darts !) for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,1+i)); } else { for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,0)); } // and continue to traverse the map std::vector* tempo = new std::vector[nbth]; for (unsigned int i=0; ijoin(); delete threads[i]; } // and release memory delete[] threads; delete[] vd; delete[] tempo; } /** * Traverse cells of a map in parallel. Use embedding marker * Functor application must be independant * @param map the map * @param orbit the cell (VERTEX/EDGE/FACE/.. * @param func the functor to apply * @param nbth number of thread to use (use twice as threads of processor) * @param szbuff size of buffers to store darts in each thread (default is 8192, use less for lower memory consumsion) * @param good a selector */ template void foreach_cell(typename PFP::MAP& map, unsigned int cell, FunctorMapThreaded& func, unsigned int nbth, unsigned int szbuff, bool needMarkers, const FunctorSelect& good) { std::vector* vd = new std::vector[nbth]; boost::thread** threads = new boost::thread*[nbth]; CellMarker cm(map,cell); Dart d=map.begin(); // nbth new functions, new thread (with good darts !) for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,1+i)); } else { for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,0)); } // and continue to traverse the map std::vector* tempo = new std::vector[nbth]; for (unsigned int i=0; ijoin(); delete threads[i]; } delete[] threads; delete[] vd; delete[] tempo; } template void foreach_dart(typename PFP::MAP& map, FunctorMapThreaded& func, unsigned int nbth, unsigned int szbuff, bool needMarkers, const FunctorSelect& good) { std::vector* vd = new std::vector[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(func, vd[i],sync1,sync2, finished,1+i)); } else { for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,0)); } // and continue to traverse the map std::vector* tempo = new std::vector[nbth]; for (unsigned int i=0; ijoin(); delete threads[i]; } delete vd; delete threads; delete tempo; } template void foreach_orbit_res(typename PFP::MAP& map, unsigned int orbit, FunctorMapThreadedResult& func, unsigned int nbth, unsigned int szbuff, std::vector& results, bool needMarkers, const FunctorSelect& good) { std::vector* vd = new std::vector[nbth]; boost::thread** threads = new boost::thread*[nbth]; ThreadFunctionResult** th_funcs= new ThreadFunctionResult*[nbth]; DartMarker dm(map); Dart d=map.begin(); // nbth new functions, new thread (with good darts !) for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,1+i,results[i]); threads[i] = new boost::thread(*(th_funcs[i])); } } else { for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,0,results[i]); threads[i] = new boost::thread(*(th_funcs[i])); } } // and continue to traverse the map std::vector* tempo = new std::vector[nbth]; for (unsigned int i=0; i res; //wait for all theads to be finished and get results for (unsigned int i=0; i< nbth; ++i) { threads[i]->join(); delete threads[i]; th_funcs[i]->clean(); } //release dynamic allocation delete[] threads; delete[] vd; delete[] th_funcs; delete[] tempo; } template void foreach_cell_res(typename PFP::MAP& map, unsigned int cell, FunctorMapThreadedResult& func, unsigned int nbth, unsigned int szbuff, std::vector& results, bool needMarkers, const FunctorSelect& good) { std::vector* vd = new std::vector[nbth]; boost::thread** threads = new boost::thread*[nbth]; ThreadFunctionResult** th_funcs= new ThreadFunctionResult*[nbth]; CellMarker cm(map,cell); Dart d=map.begin(); // nbth new functions, new thread (with good darts !) for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,1+i,results[i]); threads[i] = new boost::thread(*(th_funcs[i])); } } else { for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,0,results[i]); threads[i] = new boost::thread(*(th_funcs[i])); } } // and continue to traverse the map std::vector* tempo = new std::vector[nbth]; for (unsigned int i=0; i res; //wait for all theads to be finished and get results for (unsigned int i=0; i< nbth; ++i) { threads[i]->join(); delete threads[i]; th_funcs[i]->clean(); } delete[] threads; delete[] vd; delete[] th_funcs; delete[] tempo; } template void foreach_dart_res(typename PFP::MAP& map, FunctorMapThreadedResult& func, unsigned int nbth, unsigned int szbuff, std::vector& results, bool needMarkers, const FunctorSelect& good) { std::vector* vd = new std::vector[nbth]; boost::thread** threads = new boost::thread*[nbth]; ThreadFunctionResult** th_funcs= new ThreadFunctionResult*[nbth]; Dart d=map.begin(); // nbth new functions, new thread (with good darts !) for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,1+i,results[i]); threads[i] = new boost::thread(*(th_funcs[i])); } } else { for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,0,results[i]); threads[i] = new boost::thread(*(th_funcs[i])); } } // and continue to traverse the map std::vector* tempo = new std::vector[nbth]; for (unsigned int i=0; i res; //wait for all theads to be finished and get results for (unsigned int i=0; i< nbth; ++i) { threads[i]->join(); delete threads[i]; th_funcs[i]->clean(); } delete[] threads; delete[] vd; delete[] th_funcs; delete[] tempo; } template T sumResult(const std::vector& res) { T sum(res.front()); typename std::vector::const_iterator it=res.begin(); it++; while (it != res.end()) { sum += *it; ++it; } return sum; } template std::pair sumPairResult(const std::vector< std::pair >& res) { T1 sum1(res.front().first); T2 sum2(res.front().second); typename std::vector< std::pair >::const_iterator it=res.begin(); it++; while (it != res.end()) { sum1 += it->first; sum2 += it->second; ++it; } return std::pair(sum1,sum2); } template T maxResult(const std::vector& res) { T maxr(res.front()); typename std::vector::const_iterator it=res.begin(); it++; while (it != res.end()) { if (*it > maxr) maxr = *it; ++it; } return maxr; } template T minResult(const std::vector& res) { T minr(res.front()); typename std::vector::const_iterator it=res.begin(); it++; while (it != res.end()) { if (*it < minr) minr = *it; ++it; } return minr; } } } // end namespace }