Reference documentation for deal.II version GIT 6d02bd1105 2022-05-22 03:35:01+00:00
\(\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 
47 namespace 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 #ifdef DEAL_II_WITH_TBB
78  template <typename Iterator, typename Functor>
79  void
80  parallel_for(Iterator x_begin,
81  Iterator x_end,
82  const Functor & functor,
83  const unsigned int grainsize)
84  {
85  tbb::parallel_for(tbb::blocked_range<Iterator>(x_begin, x_end, grainsize),
86  functor,
87  tbb::auto_partitioner());
88  }
89 
90 
91 
95  template <typename Iterator, typename Functor>
96  void
97  parallel_for(Iterator x_begin,
98  Iterator x_end,
99  const Functor & functor,
100  const unsigned int grainsize,
101  const std::shared_ptr<tbb::affinity_partitioner> &partitioner)
102  {
103  tbb::parallel_for(tbb::blocked_range<Iterator>(x_begin, x_end, grainsize),
104  functor,
105  *partitioner);
106  }
107 #endif
108  } // namespace internal
109 
133  template <typename InputIterator, typename OutputIterator, typename Predicate>
134  void
135  transform(const InputIterator &begin_in,
136  const InputIterator &end_in,
137  OutputIterator out,
138  const Predicate & predicate,
139  const unsigned int grainsize)
140  {
141 #ifndef DEAL_II_WITH_TBB
142  // make sure we don't get compiler
143  // warnings about unused arguments
144  (void)grainsize;
145 
146  for (OutputIterator in = begin_in; in != end_in;)
147  *out++ = predicate(*in++);
148 #else
149  using Iterators = std::tuple<InputIterator, OutputIterator>;
150  using SyncIterators = SynchronousIterators<Iterators>;
151  Iterators x_begin(begin_in, out);
152  Iterators x_end(end_in, OutputIterator());
154  SyncIterators(x_begin),
155  SyncIterators(x_end),
156  [predicate](const auto &range) {
157  for (const auto &p : range)
158  *std::get<1>(p) = predicate(*std::get<0>(p));
159  },
160  grainsize);
161 #endif
162  }
163 
164 
165 
189  template <typename InputIterator1,
190  typename InputIterator2,
191  typename OutputIterator,
192  typename Predicate>
193  void
194  transform(const InputIterator1 &begin_in1,
195  const InputIterator1 &end_in1,
196  InputIterator2 in2,
197  OutputIterator out,
198  const Predicate & predicate,
199  const unsigned int grainsize)
200  {
201 #ifndef DEAL_II_WITH_TBB
202  // make sure we don't get compiler
203  // warnings about unused arguments
204  (void)grainsize;
205 
206  for (OutputIterator in1 = begin_in1; in1 != end_in1;)
207  *out++ = predicate(*in1++, *in2++);
208 #else
209  using Iterators =
210  std::tuple<InputIterator1, InputIterator2, OutputIterator>;
211  using SyncIterators = SynchronousIterators<Iterators>;
212  Iterators x_begin(begin_in1, in2, out);
213  Iterators x_end(end_in1, InputIterator2(), OutputIterator());
215  SyncIterators(x_begin),
216  SyncIterators(x_end),
217  [predicate](const auto &range) {
218  for (const auto &p : range)
219  *std::get<2>(p) = predicate(*std::get<0>(p), *std::get<1>(p));
220  },
221  grainsize);
222 #endif
223  }
224 
225 
226 
250  template <typename InputIterator1,
251  typename InputIterator2,
252  typename InputIterator3,
253  typename OutputIterator,
254  typename Predicate>
255  void
256  transform(const InputIterator1 &begin_in1,
257  const InputIterator1 &end_in1,
258  InputIterator2 in2,
259  InputIterator3 in3,
260  OutputIterator out,
261  const Predicate & predicate,
262  const unsigned int grainsize)
263  {
264 #ifndef DEAL_II_WITH_TBB
265  // make sure we don't get compiler
266  // warnings about unused arguments
267  (void)grainsize;
268 
269  for (OutputIterator in1 = begin_in1; in1 != end_in1;)
270  *out++ = predicate(*in1++, *in2++, *in3++);
271 #else
272  using Iterators = std::
273  tuple<InputIterator1, InputIterator2, InputIterator3, OutputIterator>;
274  using SyncIterators = SynchronousIterators<Iterators>;
275  Iterators x_begin(begin_in1, in2, in3, out);
276  Iterators x_end(end_in1,
277  InputIterator2(),
278  InputIterator3(),
279  OutputIterator());
281  SyncIterators(x_begin),
282  SyncIterators(x_end),
283  [predicate](const auto &range) {
284  for (const auto &p : range)
285  *std::get<3>(p) =
286  predicate(*std::get<0>(p), *std::get<1>(p), *std::get<2>(p));
287  },
288  grainsize);
289 #endif
290  }
291 
292 
293  namespace internal
294  {
295 #ifdef DEAL_II_WITH_TBB
300  template <typename RangeType, typename Function>
301  void
302  apply_to_subranges(const tbb::blocked_range<RangeType> &range,
303  const Function & f)
304  {
305  f(range.begin(), range.end());
306  }
307 #endif
308  } // namespace internal
309 
310 
380  template <typename RangeType, typename Function>
381  void
382  apply_to_subranges(const RangeType & begin,
383  const typename identity<RangeType>::type &end,
384  const Function & f,
385  const unsigned int grainsize)
386  {
387 #ifndef DEAL_II_WITH_TBB
388  // make sure we don't get compiler
389  // warnings about unused arguments
390  (void)grainsize;
391 
392  f(begin, end);
393 #else
395  begin,
396  end,
397  [&f](const tbb::blocked_range<RangeType> &range) {
398  internal::apply_to_subranges<RangeType, Function>(range, f);
399  },
400  grainsize);
401 #endif
402  }
403 
404 
405 
434  {
439  virtual ~ParallelForInteger() = default;
440 
449  void
450  apply_parallel(const std::size_t begin,
451  const std::size_t end,
452  const std::size_t minimum_parallel_grain_size) const;
453 
460  virtual void
461  apply_to_subrange(const std::size_t, const std::size_t) const = 0;
462  };
463 
464 
465 
526  template <typename ResultType, typename RangeType, typename Function>
527  ResultType
529  const RangeType & begin,
530  const typename identity<RangeType>::type &end,
531  const unsigned int grainsize)
532  {
533 #ifndef DEAL_II_WITH_TBB
534  // make sure we don't get compiler
535  // warnings about unused arguments
536  (void)grainsize;
537 
538  return f(begin, end);
539 #else
540  return tbb::parallel_reduce(
541  tbb::blocked_range<RangeType>(begin, end, grainsize),
542  ResultType(0),
543  [f](const auto &range, const ResultType &starting_value) {
544  ResultType value = starting_value;
545  value += f(range.begin(), range.end());
546  return value;
547  },
548  std::plus<ResultType>(),
549  tbb::auto_partitioner());
550 #endif
551  }
552 
553 
554  // --------------------- for loop affinity partitioner -----------------------
555 
565  namespace internal
566  {
568  {
569  public:
573  TBBPartitioner();
574 
575 #ifdef DEAL_II_WITH_TBB
580  ~TBBPartitioner();
581 
588  std::shared_ptr<tbb::affinity_partitioner>
590 
596  void
597  release_one_partitioner(std::shared_ptr<tbb::affinity_partitioner> &p);
598 
599  private:
604  std::shared_ptr<tbb::affinity_partitioner> my_partitioner;
605 
610  bool in_use;
611 
615  std::mutex mutex;
616 #endif
617  };
618  } // namespace internal
619 } // namespace parallel
620 
621 
622 namespace internal
623 {
624  namespace VectorImplementation
625  {
640  extern unsigned int minimum_parallel_grain_size;
641  } // namespace VectorImplementation
642 
643 
644  namespace SparseMatrixImplementation
645  {
651  extern unsigned int minimum_parallel_grain_size;
652  } // namespace SparseMatrixImplementation
653 
654 } // end of namespace internal
655 
656 
657 /* --------------------------- inline functions ------------------------- */
658 
659 namespace parallel
660 {
661  inline void
663  const std::size_t begin,
664  const std::size_t end,
665  const std::size_t minimum_parallel_grain_size) const
666  {
667 #ifndef DEAL_II_WITH_TBB
668  // make sure we don't get compiler
669  // warnings about unused arguments
671 
673 #else
675  begin,
676  end,
677  [this](const tbb::blocked_range<std::size_t> &range) {
678  apply_to_subrange(range.begin(), range.end());
679  },
681 #endif
682  }
683 
684 } // end of namespace parallel
685 
687 
688 #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:604
void release_one_partitioner(std::shared_ptr< tbb::affinity_partitioner > &p)
Definition: parallel.cc:88
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:416
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition: config.h:430
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:417
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition: config.h:469
VectorType::value_type * begin(VectorType &V)
VectorType::value_type * end(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:80
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:97
void apply_to_subranges(const tbb::blocked_range< RangeType > &range, const Function &f)
Definition: parallel.h:302
ResultType accumulate_from_subranges(const Function &f, const RangeType &begin, const typename identity< RangeType >::type &end, const unsigned int grainsize)
Definition: parallel.h:528
void apply_to_subranges(const RangeType &begin, const typename identity< RangeType >::type &end, const Function &f, const unsigned int grainsize)
Definition: parallel.h:382
void transform(const InputIterator &begin_in, const InputIterator &end_in, OutputIterator out, const Predicate &predicate, const unsigned int grainsize)
Definition: parallel.h:135
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:662