threads_tbb.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 #ifndef LIBMESH_THREADS_TBB_H
20 #define LIBMESH_THREADS_TBB_H
21 
22 // Do not try to #include this header directly, it is designed to be
23 // #included directly by threads.h
24 #ifndef LIBMESH_SQUASH_HEADER_WARNING
25 # warning "This file is designed to be included through libmesh/threads.h"
26 #else
27 
28 #ifdef LIBMESH_HAVE_TBB_API
29 
30 // libMesh includes
32 
34 
35 // Threading building blocks includes
36 #include "tbb/tbb_stddef.h"
37 #include "tbb/blocked_range.h"
38 #include "tbb/parallel_for.h"
39 #include "tbb/parallel_reduce.h"
40 #include "tbb/task_scheduler_init.h"
41 #include "tbb/partitioner.h"
42 #include "tbb/spin_mutex.h"
43 #include "tbb/recursive_mutex.h"
44 #include "tbb/atomic.h"
45 #include "tbb/tbb_thread.h"
46 #include "tbb/enumerable_thread_specific.h"
47 
49 
50 #define TBB_VERSION_LESS_THAN(major,minor) \
51  ((LIBMESH_DETECTED_TBB_VERSION_MAJOR < (major) || \
52  (LIBMESH_DETECTED_TBB_VERSION_MAJOR == (major) && (LIBMESH_DETECTED_TBB_VERSION_MINOR < (minor)))) ? 1 : 0)
53 
54 // Thread-Local-Storage macros
55 #define LIBMESH_TLS_TYPE(type) tbb::enumerable_thread_specific<type>
56 #define LIBMESH_TLS_REF(value) (value).local()
57 
58 namespace libMesh
59 {
60 
61 namespace Threads
62 {
63 
68 typedef tbb::tbb_thread Thread;
69 
74 
79 typedef tbb::split split;
80 
85 template <typename Range, typename Body>
86 inline
87 void parallel_for (const Range & range, const Body & body)
88 {
90 
91 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
92  const bool logging_was_enabled = libMesh::perflog.logging_enabled();
93 
94  if (libMesh::n_threads() > 1)
96 #endif
97 
98  if (libMesh::n_threads() > 1)
99  tbb::parallel_for (range, body, tbb::auto_partitioner());
100 
101  else
102  body(range);
103 
104 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
105  if (libMesh::n_threads() > 1 && logging_was_enabled)
107 #endif
108 }
109 
110 
111 
116 template <typename Range, typename Body, typename Partitioner>
117 inline
118 void parallel_for (const Range & range, const Body & body, const Partitioner & partitioner)
119 {
120  BoolAcquire b(in_threads);
121 
122 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
123  const bool logging_was_enabled = libMesh::perflog.logging_enabled();
124 
125  if (libMesh::n_threads() > 1)
127 #endif
128 
129  if (libMesh::n_threads() > 1)
130  tbb::parallel_for (range, body, partitioner);
131 
132  else
133  body(range);
134 
135 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
136  if (libMesh::n_threads() > 1 && logging_was_enabled)
138 #endif
139 }
140 
141 
142 
147 template <typename Range, typename Body>
148 inline
149 void parallel_reduce (const Range & range, Body & body)
150 {
151  BoolAcquire b(in_threads);
152 
153 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
154  const bool logging_was_enabled = libMesh::perflog.logging_enabled();
155 
156  if (libMesh::n_threads() > 1)
158 #endif
159 
160  if (libMesh::n_threads() > 1)
161  tbb::parallel_reduce (range, body, tbb::auto_partitioner());
162 
163  else
164  body(range);
165 
166 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
167  if (libMesh::n_threads() > 1 && logging_was_enabled)
169 #endif
170 }
171 
172 
173 
178 template <typename Range, typename Body, typename Partitioner>
179 inline
180 void parallel_reduce (const Range & range, Body & body, const Partitioner & partitioner)
181 {
182  BoolAcquire b(in_threads);
183 
184 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
185  const bool logging_was_enabled = libMesh::perflog.logging_enabled();
186 
187  if (libMesh::n_threads() > 1)
189 #endif
190 
191  if (libMesh::n_threads() > 1)
192  tbb::parallel_reduce (range, body, partitioner);
193 
194  else
195  body(range);
196 
197 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
198  if (libMesh::n_threads() > 1 && logging_was_enabled)
200 #endif
201 }
202 
203 
204 
210 
217 
223 template <typename T>
224 class atomic : public tbb::atomic<T> {};
225 
226 } // namespace Threads
227 
228 } // namespace libMesh
229 
230 #endif // LIBMESH_HAVE_TBB_API
231 
232 #endif // LIBMESH_SQUASH_HEADER_WARNING
233 
234 #endif // LIBMESH_THREADS_TBB_H
NonConcurrentThread Thread
Definition: threads_none.h:43
unsigned int n_threads()
Definition: libmesh_base.h:96
void parallel_for(const Range &range, const Body &body)
Definition: threads_none.h:73
void enable_logging()
Definition: perf_log.h:161
bool in_threads
Definition: threads.C:31
PerfLog perflog("libMesh", #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING true #else false #endif)
Base class for all concrete Partitioner instantiations.
Definition: partitioner.h:50
tbb::task_scheduler_init task_scheduler_init
Definition: threads_tbb.h:73
bool logging_enabled() const
Definition: perf_log.h:166
tbb::spin_mutex spin_mutex
Definition: threads_tbb.h:209
tbb::split split
Definition: threads_tbb.h:79
void parallel_reduce(const Range &range, Body &body)
Definition: threads_none.h:101
tbb::recursive_mutex recursive_mutex
Definition: threads_tbb.h:216
void disable_logging()
Definition: perf_log.h:156