1#ifndef DUNE_FEM_MPIMANAGER_HH
2#define DUNE_FEM_MPIMANAGER_HH
4#if defined _OPENMP || defined(USE_PTHREADS)
5#ifndef USE_SMP_PARALLEL
6#define USE_SMP_PARALLEL
52 const char*
what() const noexcept
override
54 return "SingleThreadModeError: remove -DNDEBUG to obtain a more detailed message!";
63 static inline unsigned int getEnvNumberThreads (
unsigned int defaultValue)
65#ifdef USE_SMP_PARALLEL
66 unsigned int maxThreads = defaultValue;
68 const char* mThreads =
std::getenv(
"DUNE_NUM_THREADS");
73 const char* mThreads =
std::getenv(
"OMP_NUM_THREADS");
78 unsigned int maxThreads = 1;
86 static const bool useStdThreads = true ;
87 static_assert( useStdThreads,
"useStdThreads is disabled but OpenMP has not been found!");
90 static const bool useStdThreads = false ;
113 static int& threadNumber_()
115 static thread_local int number = -1;
123 ThreadPool::threadNumber_() = t;
133 while (!run_ && !finalized_)
136 if (finalized_)
break;
137 ThreadPool::threadNumber_() = t;
153 template<
typename F,
typename... Args>
154 void runOpenMP(F&& f, Args&&... args)
157 const int nThreads = numThreads();
166 initMultiThreadMode();
167#pragma omp parallel num_threads(nThreads)
170 threadNumber_() = omp_get_thread_num();
181 singleThreadModeError = true ;
187 initSingleThreadMode();
190 if( singleThreadModeError )
192 DUNE_THROW(SingleThreadModeError,
"ThreadPool::run: single thread mode violation occurred!");
205 : maxThreads_(
std::
max(1u, detail::getEnvNumberThreads(
std::thread::hardware_concurrency() )) )
206 , numThreads_( detail::getEnvNumberThreads(1) )
213 ThreadPool::threadNumber_() = 0;
214#ifdef USE_SMP_PARALLEL
215 if constexpr( useStdThreads )
218 for (
int t=1;t<maxThreads_;++t)
221 numbers_[threads_[t-1].get_id()] = t;
228#ifdef USE_SMP_PARALLEL
229 if constexpr( useStdThreads )
244 template<
typename F,
typename... Args>
245 void run(F&& f, Args&&... args)
251 Dune::Fem::detail::SingletonStorage::getStorage();
252 if (!singleThreadMode())
253 DUNE_THROW(InvalidStateException,
"ThreadPool: run is running run");
254 if constexpr(! useStdThreads )
256 runOpenMP(f, args...);
259 if ( numThreads_==1 )
266 initMultiThreadMode();
274 catch (
const SingleThreadModeError& e )
275 { caughtException =
true; }
281 ThreadPool::threadNumber_() = 0;
293 initSingleThreadMode();
294 if( caughtException )
295 DUNE_THROW(SingleThreadModeError,
"ThreadPool::run: single thread mode violation occurred!");
299 int numThreads()
const {
return numThreads_; }
300 int maxThreads()
const {
return maxThreads_; }
306 int t = ThreadPool::threadNumber_();
315 if constexpr(! useStdThreads )
316 return omp_get_thread_num();
326 [[deprecated(
"Use method thread instead!")]]
327 int threadNumber()
const {
return thread(); }
329 void initSingleThreadMode() { activeThreads_ = 1; }
330 void initMultiThreadMode() { activeThreads_ = numThreads_; }
331 bool singleThreadMode()
const {
return activeThreads_ == 1; }
332 void setNumThreads(
int use )
334 if ( !singleThreadMode() )
335 DUNE_THROW(SingleThreadModeError,
"ThreadPool: number of threads can only be changed in single thread mode!");
336 if ( use > maxThreads_ )
338 std::cout <<
"Warning: requesting more threads than available."
339 <<
" Maximum number of threads was restricted to " << maxThreads_
340 <<
" at startup. Setting to maximum number instead.\n";
346 bool isMainThread()
const {
return thread() == 0; }
364 static bool mpiFinalized ()
366 bool finalized = false ;
370 int wasFinalized = -1;
371 MPI_Finalized( &wasFinalized );
372 finalized = bool( wasFinalized );
387 if( ! mpiFinalized() )
390 if( petscWasInitializedHere_ )
391 ::Dune::Petsc::finalize();
395 if( wasInitializedHere_ )
409 static void initialize (
int &argc,
char **&argv );
439 static int maxThreads() {
return instance().pool_.maxThreads(); }
442 static int numThreads() {
return instance().pool_.numThreads(); }
445 static int thread() {
return instance().pool_.thread(); }
450 [[deprecated(
"use isMainThread() instead!")]]
454 static void setNumThreads(
int use ) { instance().pool_.setNumThreads(use); }
460 template<
typename F,
typename... Args>
461 static void run(F&& f, Args&&... args) { instance().pool_.run(f,args...); }
466 bool wasInitializedHere_ = false ;
468 bool petscWasInitializedHere_ = false ;
489 class QuadratureStorageRegistry;
499 int wasInitialized = -1;
500 MPI_Initialized( &wasInitialized );
503#ifndef USE_SMP_PARALLEL
508 int is_initialized = MPI_Init(&argc, &argv);
509 if( is_initialized != MPI_SUCCESS )
516 int is_initialized = MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided );
518 if( is_initialized != MPI_SUCCESS )
521#if not defined NDEBUG && defined DUNE_DEVEL_MODE
525 if( provided != MPI_THREAD_FUNNELED )
527 if( provided == MPI_THREAD_SINGLE )
528 dwarn <<
"MPI thread support = single (instead of funneled)!" <<
std::endl;
530 dwarn <<
"WARNING: MPI thread support = " << provided <<
" != MPI_THREAD_FUNNELED " << MPI_THREAD_FUNNELED <<
std::endl;
535 instance().wasInitializedHere_ =
true;
552 instance().petscWasInitializedHere_ =
553 ::Dune::Petsc::initialize(
rank() == 0, argc, argv );
#define DUNE_THROW(E,...)
MPIManager ThreadPool
Definition mpimanager.hh:477
static double max(const Double &v, const double p)
Definition double.hh:398
static DUNE_EXPORT MPIHelper & instance(int &argc, char **&argv)
static MPICommunicator getCommunicator()
Exception thrown when a code segment that is supposed to be only accessed in single thread mode is ac...
Definition mpimanager.hh:43
void message(const std::string &msg)
Definition mpimanager.hh:48
const char * what() const noexcept override
Definition mpimanager.hh:49
std::string msg_
Definition mpimanager.hh:47
Definition mpimanager.hh:353
detail::ThreadPool ThreadPoolType
Definition mpimanager.hh:357
static void run(F &&f, Args &&... args)
run functor f with given arguments args in threaded mode
Definition mpimanager.hh:461
static int thread()
return thread number
Definition mpimanager.hh:445
static void finalize()
Definition mpimanager.hh:404
static bool isMainThread()
return true if the current thread is the main thread (i.e. thread 0)
Definition mpimanager.hh:448
static int maxThreads()
return maximal number of threads possible in the current run
Definition mpimanager.hh:439
static bool isMaster()
Definition mpimanager.hh:451
static bool singleThreadMode()
returns true if program is operating on one thread currently
Definition mpimanager.hh:457
Dune::Communication< MPIHelper::MPICommunicator > Communication
Definition mpimanager.hh:355
static void initMultiThreadMode()
initialize multi thread mode (when in single thread mode)
Definition mpimanager.hh:436
static void setNumThreads(int use)
set number of threads available during next run
Definition mpimanager.hh:454
static void initSingleThreadMode()
initialize single thread mode (when in multithread mode)
Definition mpimanager.hh:433
~MPIManager()
destructor calling finalize if this has not been done
Definition mpimanager.hh:380
static const Communication & comm()
Definition mpimanager.hh:411
static int size()
Definition mpimanager.hh:424
static int rank()
Definition mpimanager.hh:419
static void initialize(int &argc, char **&argv)
Definition mpimanager.hh:491
void _finalize()
Definition mpimanager.hh:385
static const ThreadPoolType & threadPool()
return reference to ThreadPool instance (for caching and efficiency purposes)
Definition mpimanager.hh:430
static int numThreads()
return number of current threads
Definition mpimanager.hh:442
static void initialize()
initialize static variables
Definition registry.hh:64
return singleton instance of given Object type.
Definition singleton.hh:93