/********************************************************************************
* *
* P a r a l l e l C o m p u t a t i o n *
* *
*********************************************************************************
* Copyright (C) 2012,2024 by Jeroen van der Zijp. All Rights Reserved. *
*********************************************************************************
* 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 3 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 program. If not, see *
********************************************************************************/
#ifndef FXPARALLEL_H
#define FXPARALLEL_H
namespace FX {
enum{
FXParallelMax=128 // Maximum number of parallel jobs
};
/**
* FXParallelCallFunctor is a helper for FXParallelInvoke. It executes a functor on
* a thread provided by the FXThreadPool.
*/
template
class FXParallelCallFunctor : public FXRunnable {
const Functor& functor;
private:
FXParallelCallFunctor(const FXParallelCallFunctor&);
FXParallelCallFunctor &operator=(const FXParallelCallFunctor&);
public:
FXParallelCallFunctor(const Functor& fun):functor(fun){ }
virtual FXint run(){ functor(); return 0; }
};
/**
* Perform a parallel call to functors fun1 and fun2 using the given FXThreadPool.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(FXThreadPool* pool,const Functor1& fun1,const Functor2& fun2){
FXTaskGroup group(pool);
FXParallelCallFunctor task1(fun1);
FXParallelCallFunctor task2(fun2);
group.execute(&task1);
group.executeAndWait(&task2);
}
/**
* Perform a parallel call to functors fun1 and fun2 using the FXThreadPool
* associated with the calling thread.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(const Functor1& fun1,const Functor2& fun2){
FXParallelInvoke(FXThreadPool::instance(),fun1,fun2);
}
/**
* Perform a parallel call to functors fun1, fun2, and fun3, using the given FXThreadPool.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(FXThreadPool* pool,const Functor1& fun1,const Functor2& fun2,const Functor3& fun3){
FXTaskGroup group(pool);
FXParallelCallFunctor task1(fun1);
FXParallelCallFunctor task2(fun2);
FXParallelCallFunctor task3(fun3);
group.execute(&task1);
group.execute(&task2);
group.executeAndWait(&task3);
}
/**
* Perform a parallel call to functors fun1, fun2, and fun3, using the FXThreadPool
* associated with the calling thread.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(const Functor1& fun1,const Functor2& fun2,const Functor3& fun3){
FXParallelInvoke(FXThreadPool::instance(),fun1,fun2,fun3);
}
/**
* Perform a parallel call to functors fun1, fun2, fun3, and fun4, using the given FXThreadPool.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(FXThreadPool* pool,const Functor1& fun1,const Functor2& fun2,const Functor3& fun3,const Functor4& fun4){
FXTaskGroup group(pool);
FXParallelCallFunctor task1(fun1);
FXParallelCallFunctor task2(fun2);
FXParallelCallFunctor task3(fun3);
FXParallelCallFunctor task4(fun4);
group.execute(&task1);
group.execute(&task2);
group.execute(&task3);
group.executeAndWait(&task4);
}
/**
* Perform a parallel call to functors fun1, fun2, fun3, and fun4, using the FXThreadPool
* associated with the calling thread.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(const Functor1& fun1,const Functor2& fun2,const Functor3& fun3,const Functor4& fun4){
FXParallelInvoke(FXThreadPool::instance(),fun1,fun2,fun3,fun4);
}
/**
* Perform a parallel call to functors fun1, fun2, fun3, fun4, and fun5, using the given FXThreadPool.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(FXThreadPool* pool,const Functor1& fun1,const Functor2& fun2,const Functor3& fun3,const Functor4& fun4,const Functor4& fun5){
FXTaskGroup group(pool);
FXParallelCallFunctor task1(fun1);
FXParallelCallFunctor task2(fun2);
FXParallelCallFunctor task3(fun3);
FXParallelCallFunctor task4(fun4);
FXParallelCallFunctor task5(fun5);
group.execute(&task1);
group.execute(&task2);
group.execute(&task3);
group.execute(&task4);
group.executeAndWait(&task5);
}
/**
* Perform a parallel call to functors fun1, fun2, fun3, fun4, and fun5, using the
* FXThreadPool associated with the calling thread.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(const Functor1& fun1,const Functor2& fun2,const Functor3& fun3,const Functor4& fun4,const Functor4& fun5){
FXParallelInvoke(FXThreadPool::instance(),fun1,fun2,fun3,fun4,fun5);
}
/**
* Perform a parallel call to functors fun1, fun2, fun3, fun4, fun5, and fun6, using the given FXThreadPool.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(FXThreadPool* pool,const Functor1& fun1,const Functor2& fun2,const Functor3& fun3,const Functor4& fun4,const Functor5& fun5,const Functor6& fun6){
FXTaskGroup group(pool);
FXParallelCallFunctor task1(fun1);
FXParallelCallFunctor task2(fun2);
FXParallelCallFunctor task3(fun3);
FXParallelCallFunctor task4(fun4);
FXParallelCallFunctor task5(fun5);
FXParallelCallFunctor task6(fun6);
group.execute(&task1);
group.execute(&task2);
group.execute(&task3);
group.execute(&task4);
group.execute(&task5);
group.executeAndWait(&task6);
}
/**
* Perform a parallel call to functors fun1, fun2, fun3, fun4, fun5, and fun6, using the
* FXThreadPool associated with the calling thread.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(Functor1& fun1,const Functor2& fun2,const Functor3& fun3,const Functor4& fun4,const Functor5& fun5,const Functor6& fun6){
FXParallelInvoke(FXThreadPool::instance(),fun1,fun2,fun3,fun4,fun5,fun6);
}
/**
* Perform a parallel call to functors fun1, fun2, fun3, fun4, fun5, fun6, and fun7, using the given FXThreadPool.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(FXThreadPool* pool,const Functor1& fun1,const Functor2& fun2,const Functor3& fun3,const Functor4& fun4,const Functor5& fun5,const Functor6& fun6,const Functor7& fun7){
FXTaskGroup group(pool);
FXParallelCallFunctor task1(fun1);
FXParallelCallFunctor task2(fun2);
FXParallelCallFunctor task3(fun3);
FXParallelCallFunctor task4(fun4);
FXParallelCallFunctor task5(fun5);
FXParallelCallFunctor task6(fun6);
FXParallelCallFunctor task7(fun7);
group.execute(&task1);
group.execute(&task2);
group.execute(&task3);
group.execute(&task4);
group.execute(&task5);
group.execute(&task6);
group.executeAndWait(&task7);
}
/**
* Perform a parallel call to functors fun1, fun2, fun3, fun4, fun5, fun6, and fun7, using the
* FXThreadPool associated with the calling thread.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(Functor1& fun1,const Functor2& fun2,const Functor3& fun3,const Functor4& fun4,const Functor5& fun5,const Functor6& fun6,const Functor7& fun7){
FXParallelInvoke(FXThreadPool::instance(),fun1,fun2,fun3,fun4,fun5,fun6,fun7);
}
/**
* Perform a parallel call to functors fun1, fun2, fun3, fun4, fun5, fun6, fun7, and fun8, using
* the given FXThreadPool.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(FXThreadPool* pool,const Functor1& fun1,const Functor2& fun2,const Functor3& fun3,const Functor4& fun4,const Functor5& fun5,const Functor6& fun6,const Functor7& fun7,const Functor8& fun8){
FXTaskGroup group(pool);
FXParallelCallFunctor task1(fun1);
FXParallelCallFunctor task2(fun2);
FXParallelCallFunctor task3(fun3);
FXParallelCallFunctor task4(fun4);
FXParallelCallFunctor task5(fun5);
FXParallelCallFunctor task6(fun6);
FXParallelCallFunctor task7(fun7);
FXParallelCallFunctor task8(fun8);
group.execute(&task1);
group.execute(&task2);
group.execute(&task3);
group.execute(&task4);
group.execute(&task5);
group.execute(&task6);
group.execute(&task7);
group.executeAndWait(&task8);
}
/**
* Perform a parallel call to functors fun1, fun2, fun3, fun4, fun5, fun6, fun7, and fun8, using the
* FXThreadPool associated with the calling thread.
* Return when all functors have completed.
*/
template
void FXParallelInvoke(Functor1& fun1,const Functor2& fun2,const Functor3& fun3,const Functor4& fun4,const Functor5& fun5,const Functor6& fun6,const Functor7& fun7,const Functor8& fun8){
FXParallelInvoke(FXThreadPool::instance(),fun1,fun2,fun3,fun4,fun5,fun6,fun7,fun8);
}
/*******************************************************************************/
/**
* FXParallelLoopFunctor is a helper for FXParallelFor. It executes a subrange of the
* global indexing range on a thread provided by the FXThreadPool.
*/
template
class FXParallelForFunctor : public FXRunnable {
const Functor& functor;
const Index fm;
const Index to;
const Index by;
private:
FXParallelForFunctor(const FXParallelForFunctor&);
FXParallelForFunctor &operator=(const FXParallelForFunctor&);
public:
FXParallelForFunctor(const Functor& fun,Index f,Index t,Index b):functor(fun),fm(f),to(t),by(b){ }
virtual FXint run(){ for(Index ix=fm;ix
void FXParallelFor(FXThreadPool* pool,Index fm,Index to,Index by,Index nc,const Functor& fun){
const FXuval size=(sizeof(FXParallelForFunctor)+sizeof(FXulong)-1)/sizeof(FXulong);
if(fm)+sizeof(FXulong)-1)/sizeof(FXulong))];
Index nits=1+(to-fm-1)/by,ni,c;
if(nc>FXParallelMax) nc=FXParallelMax;
if(nc>nits) nc=nits;
for(c=0; c(fun,fm,fm+ni*by,by));
}
group.wait();
}
else{
fun(fm);
}
}
}
/**
* Perform parallel for-loop executing functor fun(i) for indexes x=fm+by*i, where x
void FXParallelFor(Index fm,Index to,Index by,Index nc,const Functor& fun){
FXParallelFor(FXThreadPool::instance(),fm,to,by,nc,fun);
}
/**
* Perform parallel for loop executing functor fun(i) for indexes x=fm+by*i, where x
void FXParallelFor(FXThreadPool* pool,Index fm,Index to,Index by,const Functor& fun){
FXParallelFor(pool,fm,to,by,(Index)pool->getMaximumThreads(),fun);
}
/**
* Perform parallel for loop executing functor fun(i) for indexes x=fm+by*i, where x
void FXParallelFor(Index fm,Index to,Index by,const Functor& fun){
FXParallelFor(FXThreadPool::instance(),fm,to,by,fun);
}
}
#endif