22 #ifndef TLP_PARALLEL_TOOLS_H 23 #define TLP_PARALLEL_TOOLS_H 25 #include <tulip/tulipconf.h> 28 #ifndef TLP_NO_THREADS 36 typedef long long OMP_ITER_TYPE;
38 typedef size_t OMP_ITER_TYPE;
41 #define OMP(x) _Pragma(STRINGIFY(omp x)) 42 #define OMP_CRITICAL_SECTION(x) _Pragma(STRINGIFY(omp critical(x))) 44 #define OMP(x) __pragma(omp x) 45 #define OMP_CRITICAL_SECTION(x) __pragma(omp critical(x)) 74 class TLP_SCOPE ThreadManager {
76 static unsigned int maxNumberOfThreads;
78 #if !defined(TLP_NO_THREADS) && !defined(_OPENMP) 81 static void allocateThreadNumber();
84 static void freeThreadNumber();
88 template <
typename runFunction>
89 static inline std::thread *launchThread(
const runFunction &f, uint begin, uint end) {
90 auto thrdFunction = [&](uint begin, uint end) {
91 allocateThreadNumber();
95 return new std::thread(thrdFunction, begin, end);
101 #if !defined(TLP_NO_THREADS) && !defined(_OPENMP) 105 template <
typename runFunction>
106 static inline std::thread *launchThread(
const runFunction &f) {
107 auto thrdFunction = [&]() {
108 allocateThreadNumber();
112 return new std::thread(thrdFunction);
120 static unsigned int getNumberOfProcs();
125 static unsigned int getNumberOfThreads();
130 static void setNumberOfThreads(
unsigned int nbThreads);
135 static unsigned int getThreadNumber();
143 template <
typename ThreadFunction>
144 static inline void iterate(
size_t maxId,
const ThreadFunction &threadFunction) {
145 #ifndef TLP_NO_THREADS 150 size_t nbPerThread = maxId == 1 ? 1 : std::max(maxId / (maxNumberOfThreads - 1),
size_t(2));
152 size_t begin = 0, end = nbPerThread;
153 maxId -= end - begin;
155 std::vector<std::thread *> threads;
156 threads.reserve(maxNumberOfThreads - 1);
158 threads.push_back(launchThread(threadFunction, begin, end));
159 if (nbPerThread > 1) {
160 if (maxNumberOfThreads - threads.size() == maxId)
164 end += std::min(nbPerThread, maxId);
165 maxId -= end - begin;
168 threadFunction(begin, end);
170 for (
auto thrd : threads) {
175 threadFunction(0, maxId);
182 #ifndef TLP_NO_THREADS 184 #define TLP_MAX_NB_THREADS 128 186 #define TLP_NB_THREADS tlp::ThreadManager::getNumberOfThreads() 208 #define TLP_LOCK_SECTION(mtx) \ 209 static tlp::OpenMPLock mtx; \ 211 #define TLP_UNLOCK_SECTION(mtx) mtx.unlock(); 212 #define TLP_DECLARE_GLOBAL_LOCK(mtx) extern tlp::OpenMPLock mtx 213 #define TLP_DEFINE_GLOBAL_LOCK(mtx) tlp::OpenMPLock mtx 214 #define TLP_GLOBALLY_LOCK_SECTION(mtx) mtx.lock(); 215 #define TLP_GLOBALLY_UNLOCK_SECTION(mtx) mtx.unlock() 219 #define TLP_LOCK_SECTION(mtx) OMP_CRITICAL_SECTION(mtx) 220 #define TLP_UNLOCK_SECTION(mtx) 221 #define TLP_DECLARE_GLOBAL_LOCK(mtx) extern void mtx() 222 #define TLP_DEFINE_GLOBAL_LOCK(mtx) extern void mtx() 223 #define TLP_GLOBALLY_LOCK_SECTION(mtx) OMP_CRITICAL_SECTION(mtx) 224 #define TLP_GLOBALLY_UNLOCK_SECTION(mtx) 230 #define TLP_LOCK_SECTION(mtx) \ 231 static std::mutex mtx; \ 233 #define TLP_UNLOCK_SECTION(mtx) mtx.unlock() 234 #define TLP_DECLARE_GLOBAL_LOCK(mtx) extern std::mutex mtx 235 #define TLP_DEFINE_GLOBAL_LOCK(mtx) std::mutex mtx 236 #define TLP_GLOBALLY_LOCK_SECTION(mtx) mtx.lock(); 237 #define TLP_GLOBALLY_UNLOCK_SECTION(mtx) mtx.unlock() 244 #define TLP_MAX_NB_THREADS 1 246 #define TLP_NB_THREADS 1 248 #define TLP_LOCK_SECTION(mtx) 249 #define TLP_UNLOCK_SECTION(mtx) 250 #define TLP_DECLARE_GLOBAL_LOCK(mtx) extern void mtx() 251 #define TLP_DEFINE_GLOBAL_LOCK(mtx) extern void mtx() 252 #define TLP_GLOBALLY_LOCK_SECTION(mtx) 253 #define TLP_GLOBALLY_UNLOCK_SECTION(mtx) 284 template <
typename IdxFunction>
285 void inline TLP_PARALLEL_MAP_INDICES(
size_t maxIdx,
const IdxFunction &idxFunction) {
288 for (OMP_ITER_TYPE i = 0; i < OMP_ITER_TYPE(maxIdx); ++i) {
292 auto threadFunction = [&](
size_t begin,
size_t end) {
293 for (; begin < end; ++begin) {
297 ThreadManager::iterate(maxIdx, threadFunction);
301 template <
typename EltType,
typename IdxFunction>
302 void inline TLP_PARALLEL_MAP_VECTOR(
const std::vector<EltType> &vect,
303 const IdxFunction &idxFunction) {
305 auto maxIdx = vect.size();
307 for (OMP_ITER_TYPE i = 0; i < OMP_ITER_TYPE(maxIdx); ++i) {
308 idxFunction(vect[i]);
311 auto threadFunction = [&](
size_t begin,
size_t end) {
312 for (; begin < end; ++begin) {
313 idxFunction(vect[begin]);
317 ThreadManager::iterate(vect.size(), threadFunction);
321 template <
typename EltType,
typename IdxFunction>
322 void inline TLP_PARALLEL_MAP_VECTOR_AND_INDICES(
const std::vector<EltType> &vect,
323 const IdxFunction &idxFunction) {
325 auto maxIdx = vect.size();
327 for (OMP_ITER_TYPE i = 0; i < OMP_ITER_TYPE(maxIdx); ++i) {
328 idxFunction(vect[i], i);
331 auto threadFunction = [&](
size_t begin,
size_t end) {
332 for (; begin < end; ++begin) {
333 idxFunction(vect[begin], begin);
337 ThreadManager::iterate(vect.size(), threadFunction);
341 template <
typename F1,
typename F2>
342 void inline TLP_PARALLEL_SECTIONS(
const F1 &f1,
const F2 &f2) {
343 #ifndef TLP_NO_THREADS 346 OMP(sections nowait) {
356 auto thrd = ThreadManager::launchThread(f1);
367 template <
typename F1,
typename F2,
typename F3>
368 void inline TLP_PARALLEL_SECTIONS(
const F1 &f1,
const F2 &f2,
const F3 &f3) {
369 #ifndef TLP_NO_THREADS 372 OMP(sections nowait) {
385 auto thrd1 = ThreadManager::launchThread(f1);
386 auto thrd2 = ThreadManager::launchThread(f2);
400 template <
typename F1,
typename F2,
typename F3,
typename F4>
401 void inline TLP_PARALLEL_SECTIONS(
const F1 &f1,
const F2 &f2,
const F3 &f3,
const F4 &f4) {
402 #ifndef TLP_NO_THREADS 405 OMP(sections nowait) {
421 auto thrd1 = ThreadManager::launchThread(f1);
422 auto thrd2 = ThreadManager::launchThread(f2);
423 auto thrd3 = ThreadManager::launchThread(f3);
441 #endif // TLP_PARALLEL_TOOLS_H