Reference documentation for deal.II version 9.3.3
\(\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\}}\)
parallel.h
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 2008 - 2020 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
26
27#include <cstddef>
28#include <functional>
29#include <memory>
30#include <tuple>
31
32#ifdef DEAL_II_WITH_TBB
34# include <tbb/blocked_range.h>
35# include <tbb/parallel_for.h>
36# include <tbb/parallel_reduce.h>
37# include <tbb/partitioner.h>
39#endif
40
41
42// TODO[WB]: allow calling functions to pass along a tbb::affinity_partitioner
43// object to ensure that subsequent calls use the same cache lines
44
46
47namespace parallel
48{
49 namespace internal
50 {
55 template <typename Number>
57 {
58 static const bool value = true;
59 };
60
61#ifdef __INTEL_COMPILER
62 // Disable long double SIMD instructions on ICC. This is to work around a
63 // bug that generates wrong code at least up to intel 15 (see
64 // tests/lac/vector-vector, tests/lac/intel-15-bug, and the discussion at
65 // https://github.com/dealii/dealii/issues/598).
66 template <>
67 struct EnableOpenMPSimdFor<long double>
68 {
69 static const bool value = false;
70 };
71#endif
72
73
74
79 template <typename F>
80 struct Body
81 {
85 Body(const F &f)
86 : f(f)
87 {}
88
89 template <typename Range>
90 void
91 operator()(const Range &range) const
92 {
93 for (typename Range::const_iterator p = range.begin(); p != range.end();
94 ++p)
95 apply(f, *p);
96 }
97
98 private:
102 const F f;
103
107 template <typename I1, typename I2>
108 static void
109 apply(const F &f, const std::tuple<I1, I2> &p)
110 {
111 *std::get<1>(p) = f(*std::get<0>(p));
112 }
113
117 template <typename I1, typename I2, typename I3>
118 static void
119 apply(const F &f, const std::tuple<I1, I2, I3> &p)
120 {
121 *std::get<2>(p) = f(*std::get<0>(p), *std::get<1>(p));
122 }
123
127 template <typename I1, typename I2, typename I3, typename I4>
128 static void
129 apply(const F &f, const std::tuple<I1, I2, I3, I4> &p)
130 {
131 *std::get<3>(p) = f(*std::get<0>(p), *std::get<1>(p), *std::get<2>(p));
132 }
133 };
134
135
136
143 template <typename F>
144 Body<F>
145 make_body(const F &f)
146 {
147 return Body<F>(f);
148 }
149
150
151
152#ifdef DEAL_II_WITH_TBB
156 template <typename Iterator, typename Functor>
157 void
158 parallel_for(Iterator x_begin,
159 Iterator x_end,
160 const Functor & functor,
161 const unsigned int grainsize)
162 {
163 tbb::parallel_for(tbb::blocked_range<Iterator>(x_begin, x_end, grainsize),
164 functor,
165 tbb::auto_partitioner());
166 }
167
168
169
173 template <typename Iterator, typename Functor>
174 void
175 parallel_for(Iterator x_begin,
176 Iterator x_end,
177 const Functor & functor,
178 const unsigned int grainsize,
179 const std::shared_ptr<tbb::affinity_partitioner> &partitioner)
180 {
181 tbb::parallel_for(tbb::blocked_range<Iterator>(x_begin, x_end, grainsize),
182 functor,
183 *partitioner);
184 }
185#endif
186 } // namespace internal
187
211 template <typename InputIterator, typename OutputIterator, typename Predicate>
212 void
213 transform(const InputIterator &begin_in,
214 const InputIterator &end_in,
215 OutputIterator out,
216 const Predicate & predicate,
217 const unsigned int grainsize)
218 {
219#ifndef DEAL_II_WITH_TBB
220 // make sure we don't get compiler
221 // warnings about unused arguments
222 (void)grainsize;
223
224 for (OutputIterator in = begin_in; in != end_in;)
225 *out++ = predicate(*in++);
226#else
227 using Iterators = std::tuple<InputIterator, OutputIterator>;
228 using SyncIterators = SynchronousIterators<Iterators>;
229 Iterators x_begin(begin_in, out);
230 Iterators x_end(end_in, OutputIterator());
231 internal::parallel_for(SyncIterators(x_begin),
232 SyncIterators(x_end),
233 internal::make_body(predicate),
234 grainsize);
235#endif
236 }
237
238
239
263 template <typename InputIterator1,
264 typename InputIterator2,
265 typename OutputIterator,
266 typename Predicate>
267 void
268 transform(const InputIterator1 &begin_in1,
269 const InputIterator1 &end_in1,
270 InputIterator2 in2,
271 OutputIterator out,
272 const Predicate & predicate,
273 const unsigned int grainsize)
274 {
275#ifndef DEAL_II_WITH_TBB
276 // make sure we don't get compiler
277 // warnings about unused arguments
278 (void)grainsize;
279
280 for (OutputIterator in1 = begin_in1; in1 != end_in1;)
281 *out++ = predicate(*in1++, *in2++);
282#else
283 using Iterators =
284 std::tuple<InputIterator1, InputIterator2, OutputIterator>;
285 using SyncIterators = SynchronousIterators<Iterators>;
286 Iterators x_begin(begin_in1, in2, out);
287 Iterators x_end(end_in1, InputIterator2(), OutputIterator());
288 internal::parallel_for(SyncIterators(x_begin),
289 SyncIterators(x_end),
290 internal::make_body(predicate),
291 grainsize);
292#endif
293 }
294
295
296
320 template <typename InputIterator1,
321 typename InputIterator2,
322 typename InputIterator3,
323 typename OutputIterator,
324 typename Predicate>
325 void
326 transform(const InputIterator1 &begin_in1,
327 const InputIterator1 &end_in1,
328 InputIterator2 in2,
329 InputIterator3 in3,
330 OutputIterator out,
331 const Predicate & predicate,
332 const unsigned int grainsize)
333 {
334#ifndef DEAL_II_WITH_TBB
335 // make sure we don't get compiler
336 // warnings about unused arguments
337 (void)grainsize;
338
339 for (OutputIterator in1 = begin_in1; in1 != end_in1;)
340 *out++ = predicate(*in1++, *in2++, *in3++);
341#else
342 using Iterators = std::
343 tuple<InputIterator1, InputIterator2, InputIterator3, OutputIterator>;
344 using SyncIterators = SynchronousIterators<Iterators>;
345 Iterators x_begin(begin_in1, in2, in3, out);
346 Iterators x_end(end_in1,
347 InputIterator2(),
348 InputIterator3(),
349 OutputIterator());
350 internal::parallel_for(SyncIterators(x_begin),
351 SyncIterators(x_end),
352 internal::make_body(predicate),
353 grainsize);
354#endif
355 }
356
357
358 namespace internal
359 {
360#ifdef DEAL_II_WITH_TBB
365 template <typename RangeType, typename Function>
366 void
367 apply_to_subranges(const tbb::blocked_range<RangeType> &range,
368 const Function & f)
369 {
370 f(range.begin(), range.end());
371 }
372#endif
373 } // namespace internal
374
375
445 template <typename RangeType, typename Function>
446 void
447 apply_to_subranges(const RangeType & begin,
448 const typename identity<RangeType>::type &end,
449 const Function & f,
450 const unsigned int grainsize)
451 {
452#ifndef DEAL_II_WITH_TBB
453 // make sure we don't get compiler
454 // warnings about unused arguments
455 (void)grainsize;
456
457 f(begin, end);
458#else
460 end,
461 [&f](const tbb::blocked_range<RangeType> &range) {
462 internal::apply_to_subranges<RangeType, Function>(
463 range, f);
464 },
465 grainsize);
466#endif
467 }
468
469
470
499 {
504 virtual ~ParallelForInteger() = default;
505
514 void
515 apply_parallel(const std::size_t begin,
516 const std::size_t end,
517 const std::size_t minimum_parallel_grain_size) const;
518
525 virtual void
526 apply_to_subrange(const std::size_t, const std::size_t) const = 0;
527 };
528
529
530
531 namespace internal
532 {
533#ifdef DEAL_II_WITH_TBB
540 template <typename ResultType, typename Function>
542 {
546 ResultType result;
547
557 template <typename Reductor>
559 const Reductor & reductor,
560 const ResultType neutral_element = ResultType())
562 , f(f)
565 {}
566
572 , f(r.f)
574 , reductor(r.reductor)
575 {}
576
581 void
583 {
585 }
586
590 template <typename RangeType>
591 void
592 operator()(const tbb::blocked_range<RangeType> &range)
593 {
594 result = reductor(result, f(range.begin(), range.end()));
595 }
596
597 private:
601 const Function f;
602
608 const ResultType neutral_element;
609
614 const std::function<ResultType(ResultType, ResultType)> reductor;
615 };
616#endif
617 } // namespace internal
618
619
680 template <typename ResultType, typename RangeType, typename Function>
681 ResultType
683 const RangeType & begin,
684 const typename identity<RangeType>::type &end,
685 const unsigned int grainsize)
686 {
687#ifndef DEAL_II_WITH_TBB
688 // make sure we don't get compiler
689 // warnings about unused arguments
690 (void)grainsize;
691
692 return f(begin, end);
693#else
695 f, std::plus<ResultType>(), 0);
696 tbb::parallel_reduce(tbb::blocked_range<RangeType>(begin, end, grainsize),
697 reductor,
698 tbb::auto_partitioner());
699 return reductor.result;
700#endif
701 }
702
703
704 // --------------------- for loop affinity partitioner -----------------------
705
715 namespace internal
716 {
718 {
719 public:
724
725#ifdef DEAL_II_WITH_TBB
731
738 std::shared_ptr<tbb::affinity_partitioner>
740
746 void
747 release_one_partitioner(std::shared_ptr<tbb::affinity_partitioner> &p);
748
749 private:
754 std::shared_ptr<tbb::affinity_partitioner> my_partitioner;
755
760 bool in_use;
761
765 std::mutex mutex;
766#endif
767 };
768 } // namespace internal
769} // namespace parallel
770
771
772namespace internal
773{
774 namespace VectorImplementation
775 {
790 extern unsigned int minimum_parallel_grain_size;
791 } // namespace VectorImplementation
792
793
794 namespace SparseMatrixImplementation
795 {
801 extern unsigned int minimum_parallel_grain_size;
802 } // namespace SparseMatrixImplementation
803
804} // end of namespace internal
805
806
807/* --------------------------- inline functions ------------------------- */
808
809namespace parallel
810{
811#ifdef DEAL_II_WITH_TBB
812
813 namespace internal
814 {
820 {
822 : worker_(worker)
823 {}
824
825 void
826 operator()(const tbb::blocked_range<std::size_t> &range) const
827 {
828 worker_.apply_to_subrange(range.begin(), range.end());
829 }
830
832 };
833 } // namespace internal
834
835#endif
836
837
838 inline void
840 const std::size_t begin,
841 const std::size_t end,
842 const std::size_t minimum_parallel_grain_size) const
843 {
844#ifndef DEAL_II_WITH_TBB
845 // make sure we don't get compiler
846 // warnings about unused arguments
848
850#else
851 internal::ParallelForWrapper worker(*this);
853#endif
854 }
855
856} // end of namespace parallel
857
859
860#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:754
void release_one_partitioner(std::shared_ptr< tbb::affinity_partitioner > &p)
Definition: parallel.cc:88
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:402
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition: config.h:416
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition: config.h:454
std::vector< value_type > split(const typename ::Triangulation< dim, spacedim >::cell_iterator &parent, const value_type parent_value)
Tensor< 2, dim, Number > F(const Tensor< 2, dim, Number > &Grad_u)
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
unsigned int minimum_parallel_grain_size
Definition: parallel.cc:34
void parallel_reduce(const Operation &op, const size_type start, const size_type end, ResultType &result, const std::shared_ptr<::parallel::internal::TBBPartitioner > &partitioner)
void parallel_for(Iterator x_begin, Iterator x_end, const Functor &functor, const unsigned int grainsize)
Definition: parallel.h:158
void parallel_for(Iterator x_begin, Iterator x_end, const Functor &functor, const unsigned int grainsize, const std::shared_ptr< tbb::affinity_partitioner > &partitioner)
Definition: parallel.h:175
void apply_to_subranges(const tbb::blocked_range< RangeType > &range, const Function &f)
Definition: parallel.h:367
Body< F > make_body(const F &f)
Definition: parallel.h:145
ResultType accumulate_from_subranges(const Function &f, const RangeType &begin, const typename identity< RangeType >::type &end, const unsigned int grainsize)
Definition: parallel.h:682
void apply_to_subranges(const RangeType &begin, const typename identity< RangeType >::type &end, const Function &f, const unsigned int grainsize)
Definition: parallel.h:447
void transform(const InputIterator &begin_in, const InputIterator &end_in, OutputIterator out, const Predicate &predicate, const unsigned int grainsize)
Definition: parallel.h:213
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:839
static void apply(const F &f, const std::tuple< I1, I2, I3 > &p)
Definition: parallel.h:119
static void apply(const F &f, const std::tuple< I1, I2 > &p)
Definition: parallel.h:109
void operator()(const Range &range) const
Definition: parallel.h:91
static void apply(const F &f, const std::tuple< I1, I2, I3, I4 > &p)
Definition: parallel.h:129
const parallel::ParallelForInteger & worker_
Definition: parallel.h:831
void operator()(const tbb::blocked_range< std::size_t > &range) const
Definition: parallel.h:826
ParallelForWrapper(const parallel::ParallelForInteger &worker)
Definition: parallel.h:821
ReductionOnSubranges(const ReductionOnSubranges &r, tbb::split)
Definition: parallel.h:570
void operator()(const tbb::blocked_range< RangeType > &range)
Definition: parallel.h:592
const std::function< ResultType(ResultType, ResultType)> reductor
Definition: parallel.h:614
void join(const ReductionOnSubranges &r)
Definition: parallel.h:582
ReductionOnSubranges(const Function &f, const Reductor &reductor, const ResultType neutral_element=ResultType())
Definition: parallel.h:558