19#ifndef LIBMESH_THREADS_TBB_H
20#define LIBMESH_THREADS_TBB_H
24#ifndef LIBMESH_SQUASH_HEADER_WARNING
25# warning "This file is designed to be included through libmesh/threads.h"
28#ifdef LIBMESH_HAVE_TBB_API
32#ifdef LIBMESH_HAVE_ONETBB
40#include "libmesh/ignore_warnings.h"
43#ifdef LIBMESH_HAVE_ONETBB
46# include "tbb/version.h"
47# include "tbb/global_control.h"
50# include "tbb/tbb_stddef.h"
51# include "tbb/task_scheduler_init.h"
52# include "tbb/atomic.h"
53# include "tbb/tbb_thread.h"
54# include "tbb/recursive_mutex.h"
58#include "tbb/blocked_range.h"
59#include "tbb/parallel_for.h"
60#include "tbb/parallel_reduce.h"
61#include "tbb/partitioner.h"
62#include "tbb/spin_mutex.h"
63#include "tbb/enumerable_thread_specific.h"
64#include "tbb/task_arena.h"
66#include "libmesh/restore_warnings.h"
68#define TBB_VERSION_LESS_THAN(major,minor) \
69 ((LIBMESH_DETECTED_TBB_VERSION_MAJOR < (major) || \
70 (LIBMESH_DETECTED_TBB_VERSION_MAJOR == (major) && (LIBMESH_DETECTED_TBB_VERSION_MINOR < (minor)))) ? 1 : 0)
73#define LIBMESH_TLS_TYPE(type) tbb::enumerable_thread_specific<type>
74#define LIBMESH_TLS_REF(value) (value).local()
88#ifndef LIBMESH_HAVE_ONETBB
89typedef tbb::tbb_thread
Thread;
101#ifndef LIBMESH_HAVE_ONETBB
112 _gc = std::make_unique<tbb::global_control>(
113 tbb::global_control::max_allowed_parallelism,
114 static_cast<std::size_t
>(n));
120 _gc = std::make_unique<tbb::global_control>(
121 tbb::global_control::max_allowed_parallelism,
122 static_cast<std::size_t
>(n));
128 std::unique_ptr<tbb::global_control>
_gc;
142template <
typename Range,
typename Body>
144void parallel_for (
const Range & range,
const Body & body,
148 "Requested n_threads (" <<
n_threads <<
") exceeds the "
158 tbb::parallel_for (range, body, tbb::auto_partitioner());
161 tbb::task_arena arena(
static_cast<int>(
n_threads));
162 arena.execute([&]{ tbb::parallel_for(range, body, tbb::auto_partitioner()); });
175template <
typename Range,
typename Body,
typename Partitioner>
181 "Requested n_threads (" <<
n_threads <<
") exceeds the "
189 DisablePerfLogInScope disable_perf;
191 tbb::parallel_for (range, body, partitioner);
194 tbb::task_arena arena(
static_cast<int>(
n_threads));
195 arena.execute([&]{ tbb::parallel_for(range, body, partitioner); });
208template <
typename Range,
typename Body>
214 "Requested n_threads (" <<
n_threads <<
") exceeds the "
222 DisablePerfLogInScope disable_perf;
224 tbb::parallel_reduce (range, body, tbb::auto_partitioner());
227 tbb::task_arena arena(
static_cast<int>(
n_threads));
228 arena.execute([&]{ tbb::parallel_reduce(range, body, tbb::auto_partitioner()); });
241template <
typename Range,
typename Body,
typename Partitioner>
243void parallel_reduce (
const Range & range, Body & body,
const Partitioner & partitioner,
247 "Requested n_threads (" <<
n_threads <<
") exceeds the "
255 DisablePerfLogInScope disable_perf;
257 tbb::parallel_reduce (range, body, partitioner);
260 tbb::task_arena arena(
static_cast<int>(
n_threads));
261 arena.execute([&]{ tbb::parallel_reduce(range, body, partitioner); });
286#ifndef LIBMESH_HAVE_ONETBB
310 std::recursive_mutex
_m;
322#ifndef LIBMESH_HAVE_ONETBB
324class atomic :
public tbb::atomic<T> {};
327class atomic :
public std::atomic<T>
The Partitioner class provides a uniform interface for partitioning algorithms.
We use a class to turn perf logging off and on within threads, to be exception-safe and to avoid forc...
We use a class to turn Threads::in_threads on and off, to be exception-safe.
Defines atomic operations which can only be executed on a single thread at a time.
scoped_lock(recursive_mutex &rm)
void acquire(recursive_mutex &)
void acquire(recursive_mutex &rm)
Dummy "splitting object" used to distinguish splitting constructors from copy constructors.
Scheduler to manage threads.
void initialize(int n=automatic)
std::unique_ptr< tbb::global_control > _gc
static const int automatic
task_scheduler_init(int n=automatic)
bool in_threads
A boolean which is true iff we are in a Threads:: function It may be useful to assert(!...
int active_threads
An integer which is set to the number of active threads when we are in a Threads:: parallel operation...
tbb::spin_mutex spin_mutex
Spin mutex.
NonConcurrentThread Thread
Use the non-concurrent placeholder.
void parallel_reduce(const Range &range, Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided reduction operation in parallel on the specified range.
RAIIAcquire< bool, true, true > BoolAcquire
void parallel_for(const Range &range, const Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided function object in parallel on the specified range.
The libMesh namespace provides an interface to certain functionality in the library.