Reference documentation for deal.II version 9.5.0
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
parallel.h
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 2008 - 2023 by the deal.II authors
4//
5// This file is part of the deal.II library.
6//
7// The deal.II library is free software; you can use it, redistribute
8// it, and/or modify it under the terms of the GNU Lesser General
9// Public License as published by the Free Software Foundation; either
10// version 2.1 of the License, or (at your option) any later version.
11// The full text of the license can be found in the file LICENSE.md at
12// the top level directory of deal.II.
13//
14// ---------------------------------------------------------------------
15
16#ifndef dealii_parallel_h
17#define dealii_parallel_h
18
19
20#include <deal.II/base/config.h>
21
23#include <deal.II/base/mutex.h>
26
27#include <cstddef>
28#include <functional>
29#include <memory>
30#include <tuple>
31
32#ifdef DEAL_II_WITH_TBB
33# include <tbb/blocked_range.h>
34# include <tbb/parallel_for.h>
35# include <tbb/parallel_reduce.h>
36# include <tbb/partitioner.h>
37#endif
38
39#ifdef DEAL_II_HAVE_CXX20
40# include <concepts>
41#endif
42
43
44// TODO[WB]: allow calling functions to pass along a tbb::affinity_partitioner
45// object to ensure that subsequent calls use the same cache lines
46
48
49namespace parallel
50{
51 namespace internal
52 {
57 template <typename Number>
59 {
60 static const bool value = true;
61 };
62
63#ifdef __INTEL_COMPILER
64 // Disable long double SIMD instructions on ICC. This is to work around a
65 // bug that generates wrong code at least up to intel 15 (see
66 // tests/lac/vector-vector, tests/lac/intel-15-bug, and the discussion at
67 // https://github.com/dealii/dealii/issues/598).
68 template <>
69 struct EnableOpenMPSimdFor<long double>
70 {
71 static const bool value = false;
72 };
73#endif
74
75
76#ifdef DEAL_II_WITH_TBB
80 template <typename Iterator, typename Functor>
81 void
82 parallel_for(Iterator x_begin,
83 Iterator x_end,
84 const Functor & functor,
85 const unsigned int grainsize)
86 {
87 tbb::parallel_for(tbb::blocked_range<Iterator>(x_begin, x_end, grainsize),
88 functor,
89 tbb::auto_partitioner());
90 }
91
92
93
97 template <typename Iterator, typename Functor>
98 void
99 parallel_for(Iterator x_begin,
100 Iterator x_end,
101 const Functor & functor,
102 const unsigned int grainsize,
103 const std::shared_ptr<tbb::affinity_partitioner> &partitioner)
104 {
105 tbb::parallel_for(tbb::blocked_range<Iterator>(x_begin, x_end, grainsize),
106 functor,
107 *partitioner);
108 }
109#endif
110 } // namespace internal
111
141 template <typename InputIterator, typename OutputIterator, typename Function>
143 (std::invocable<Function, decltype(*std::declval<InputIterator>())> &&
144 std::assignable_from<
145 decltype(*std::declval<OutputIterator>()),
146 std::invoke_result_t<Function,
147 decltype(*std::declval<InputIterator>())>>))
148 void transform(const InputIterator &begin_in,
149 const InputIterator &end_in,
150 OutputIterator out,
151 const Function & function,
152 const unsigned int grainsize)
153 {
154#ifndef DEAL_II_WITH_TBB
155 // make sure we don't get compiler
156 // warnings about unused arguments
157 (void)grainsize;
158
159 for (OutputIterator in = begin_in; in != end_in;)
160 *out++ = function(*in++);
161#else
162 using Iterators = std::tuple<InputIterator, OutputIterator>;
163 using SyncIterators = SynchronousIterators<Iterators>;
164 Iterators x_begin(begin_in, out);
165 Iterators x_end(end_in, OutputIterator());
167 SyncIterators(x_begin),
168 SyncIterators(x_end),
169 [function](const auto &range) {
170 for (const auto &p : range)
171 *std::get<1>(p) = function(*std::get<0>(p));
172 },
173 grainsize);
174#endif
175 }
176
177
178
210 template <typename InputIterator1,
211 typename InputIterator2,
212 typename OutputIterator,
213 typename Function>
215 (std::invocable<Function,
216 decltype(*std::declval<InputIterator1>()),
217 decltype(*std::declval<InputIterator2>())> &&
218 std::assignable_from<
219 decltype(*std::declval<OutputIterator>()),
220 std::invoke_result_t<Function,
221 decltype(*std::declval<InputIterator1>()),
222 decltype(*std::declval<InputIterator2>())>>))
223 void transform(const InputIterator1 &begin_in1,
224 const InputIterator1 &end_in1,
225 InputIterator2 in2,
226 OutputIterator out,
227 const Function & function,
228 const unsigned int grainsize)
229 {
230#ifndef DEAL_II_WITH_TBB
231 // make sure we don't get compiler
232 // warnings about unused arguments
233 (void)grainsize;
234
235 for (OutputIterator in1 = begin_in1; in1 != end_in1;)
236 *out++ = function(*in1++, *in2++);
237#else
238 using Iterators =
239 std::tuple<InputIterator1, InputIterator2, OutputIterator>;
240 using SyncIterators = SynchronousIterators<Iterators>;
241 Iterators x_begin(begin_in1, in2, out);
242 Iterators x_end(end_in1, InputIterator2(), OutputIterator());
244 SyncIterators(x_begin),
245 SyncIterators(x_end),
246 [function](const auto &range) {
247 for (const auto &p : range)
248 *std::get<2>(p) = function(*std::get<0>(p), *std::get<1>(p));
249 },
250 grainsize);
251#endif
252 }
253
254
255
289 template <typename InputIterator1,
290 typename InputIterator2,
291 typename InputIterator3,
292 typename OutputIterator,
293 typename Function>
295 (std::invocable<Function,
296 decltype(*std::declval<InputIterator1>()),
297 decltype(*std::declval<InputIterator2>()),
298 decltype(*std::declval<InputIterator3>())> &&
299 std::assignable_from<
300 decltype(*std::declval<OutputIterator>()),
301 std::invoke_result_t<Function,
302 decltype(*std::declval<InputIterator1>()),
303 decltype(*std::declval<InputIterator2>()),
304 decltype(*std::declval<InputIterator3>())>>))
305 void transform(const InputIterator1 &begin_in1,
306 const InputIterator1 &end_in1,
307 InputIterator2 in2,
308 InputIterator3 in3,
309 OutputIterator out,
310 const Function & function,
311 const unsigned int grainsize)
312 {
313#ifndef DEAL_II_WITH_TBB
314 // make sure we don't get compiler
315 // warnings about unused arguments
316 (void)grainsize;
317
318 for (OutputIterator in1 = begin_in1; in1 != end_in1;)
319 *out++ = function(*in1++, *in2++, *in3++);
320#else
321 using Iterators = std::
322 tuple<InputIterator1, InputIterator2, InputIterator3, OutputIterator>;
323 using SyncIterators = SynchronousIterators<Iterators>;
324 Iterators x_begin(begin_in1, in2, in3, out);
325 Iterators x_end(end_in1,
326 InputIterator2(),
327 InputIterator3(),
328 OutputIterator());
330 SyncIterators(x_begin),
331 SyncIterators(x_end),
332 [function](const auto &range) {
333 for (const auto &p : range)
334 *std::get<3>(p) =
335 function(*std::get<0>(p), *std::get<1>(p), *std::get<2>(p));
336 },
337 grainsize);
338#endif
339 }
340
341
342 namespace internal
343 {
344#ifdef DEAL_II_WITH_TBB
351 template <typename Iterator, typename Function>
352 DEAL_II_CXX20_REQUIRES((std::invocable<Function, Iterator, Iterator>))
353 void apply_to_subranges(const tbb::blocked_range<Iterator> &range,
354 const Function & f)
355 {
356 f(range.begin(), range.end());
357 }
358#endif
359 } // namespace internal
360
361
433 template <typename Iterator, typename Function>
434 DEAL_II_CXX20_REQUIRES((std::invocable<Function, Iterator, Iterator>))
435 void apply_to_subranges(const Iterator & begin,
436 const std_cxx20::type_identity_t<Iterator> &end,
437 const Function & f,
438 const unsigned int grainsize)
439 {
440#ifndef DEAL_II_WITH_TBB
441 // make sure we don't get compiler
442 // warnings about unused arguments
443 (void)grainsize;
444
445 f(begin, end);
446#else
448 begin,
449 end,
450 [&f](const tbb::blocked_range<Iterator> &range) {
451 internal::apply_to_subranges<Iterator, Function>(range, f);
452 },
453 grainsize);
454#endif
455 }
456
457
458
487 {
492 virtual ~ParallelForInteger() = default;
493
502 void
503 apply_parallel(const std::size_t begin,
504 const std::size_t end,
505 const std::size_t minimum_parallel_grain_size) const;
506
513 virtual void
514 apply_to_subrange(const std::size_t, const std::size_t) const = 0;
515 };
516
517
518
583 template <typename ResultType, typename Iterator, typename Function>
585 (std::invocable<Function, Iterator, Iterator> &&
586 std::convertible_to<std::invoke_result_t<Function, Iterator, Iterator>,
587 ResultType>))
588 ResultType
590 const Iterator & begin,
591 const std_cxx20::type_identity_t<Iterator> &end,
592 const unsigned int grainsize)
593 {
594#ifndef DEAL_II_WITH_TBB
595 // make sure we don't get compiler
596 // warnings about unused arguments
597 (void)grainsize;
598
599 return f(begin, end);
600#else
601 return tbb::parallel_reduce(
602 tbb::blocked_range<Iterator>(begin, end, grainsize),
603 ResultType(0),
604 [f](const auto &range, const ResultType &starting_value) {
605 ResultType value = starting_value;
606 value += f(range.begin(), range.end());
607 return value;
608 },
609 std::plus<ResultType>(),
610 tbb::auto_partitioner());
611#endif
612 }
613
614
615 // --------------------- for loop affinity partitioner -----------------------
616
626 namespace internal
627 {
629 {
630 public:
635
636#ifdef DEAL_II_WITH_TBB
642
649 std::shared_ptr<tbb::affinity_partitioner>
651
657 void
658 release_one_partitioner(std::shared_ptr<tbb::affinity_partitioner> &p);
659
660 private:
665 std::shared_ptr<tbb::affinity_partitioner> my_partitioner;
666
671 bool in_use;
672
677#endif
678 };
679 } // namespace internal
680} // namespace parallel
681
682
683namespace internal
684{
685 namespace VectorImplementation
686 {
701 extern unsigned int minimum_parallel_grain_size;
702 } // namespace VectorImplementation
703
704
705 namespace SparseMatrixImplementation
706 {
712 extern unsigned int minimum_parallel_grain_size;
713 } // namespace SparseMatrixImplementation
714
715} // end of namespace internal
716
717
718/* --------------------------- inline functions ------------------------- */
719
720namespace parallel
721{
722 inline void
724 const std::size_t begin,
725 const std::size_t end,
726 const std::size_t minimum_parallel_grain_size) const
727 {
728#ifndef DEAL_II_WITH_TBB
729 // make sure we don't get compiler
730 // warnings about unused arguments
731 (void)minimum_parallel_grain_size;
732
733 apply_to_subrange(begin, end);
734#else
736 begin,
737 end,
738 [this](const tbb::blocked_range<std::size_t> &range) {
739 apply_to_subrange(range.begin(), range.end());
740 },
741 minimum_parallel_grain_size);
742#endif
743 }
744
745} // end of namespace parallel
746
748
749#endif
std::shared_ptr< tbb::affinity_partitioner > acquire_one_partitioner()
Definition parallel.cc:75
std::shared_ptr< tbb::affinity_partitioner > my_partitioner
Definition parallel.h:665
void release_one_partitioner(std::shared_ptr< tbb::affinity_partitioner > &p)
Definition parallel.cc:88
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:472
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:160
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:473
unsigned int minimum_parallel_grain_size
Definition parallel.cc:34
void parallel_for(Iterator x_begin, Iterator x_end, const Functor &functor, const unsigned int grainsize)
Definition parallel.h:82
void apply_to_subranges(const tbb::blocked_range< Iterator > &range, const Function &f)
Definition parallel.h:353
void apply_to_subranges(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, const Function &f, const unsigned int grainsize)
Definition parallel.h:435
void transform(const InputIterator &begin_in, const InputIterator &end_in, OutputIterator out, const Function &function, const unsigned int grainsize)
Definition parallel.h:148
ResultType accumulate_from_subranges(const Function &f, const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, const unsigned int grainsize)
Definition parallel.h:589
virtual ~ParallelForInteger()=default
virtual void apply_to_subrange(const std::size_t, const std::size_t) const =0
void apply_parallel(const std::size_t begin, const std::size_t end, const std::size_t minimum_parallel_grain_size) const
Definition parallel.h:723