Reference documentation for deal.II version 8.1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
parallel.h
1 // ---------------------------------------------------------------------
2 // @f$Id: parallel.h 31932 2013-12-08 02:15:54Z heister @f$
3 //
4 // Copyright (C) 2008 - 2013 by the deal.II authors
5 //
6 // This file is part of the deal.II library.
7 //
8 // The deal.II library is free software; you can use it, redistribute
9 // it, and/or modify it under the terms of the GNU Lesser General
10 // Public License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 // The full text of the license can be found in the file LICENSE at
13 // the top level of the deal.II distribution.
14 //
15 // ---------------------------------------------------------------------
16 
17 #ifndef __deal2__parallel_h
18 #define __deal2__parallel_h
19 
20 
21 #include <deal.II/base/config.h>
23 #include <deal.II/base/template_constraints.h>
24 #include <deal.II/base/synchronous_iterator.h>
25 
26 #include <deal.II/base/std_cxx1x/tuple.h>
27 #include <deal.II/base/std_cxx1x/bind.h>
28 #include <deal.II/base/std_cxx1x/function.h>
29 
30 #include <cstddef>
31 
32 #ifdef DEAL_II_WITH_THREADS
33 # include <tbb/parallel_for.h>
34 # include <tbb/parallel_reduce.h>
35 # include <tbb/partitioner.h>
36 # include <tbb/blocked_range.h>
37 #endif
38 
39 
40 //TODO[WB]: allow calling functions to pass along a tbb::affinity_partitioner object to ensure that subsequent calls use the same cache lines
41 
43 
44 namespace parallel
45 {
46  namespace internal
47  {
54  template <typename F>
55  struct Body
56  {
61  Body (const F &f)
62  :
63  f (f)
64  {}
65 
66  template <typename Range>
67  void
68  operator () (const Range &range) const
69  {
70  for (typename Range::const_iterator p=range.begin();
71  p != range.end(); ++p)
72  apply (f, p.iterators);
73  }
74 
75  private:
79  const F f;
80 
85  template <typename I1, typename I2>
86  static
87  void
88  apply (const F &f,
89  const std_cxx1x::tuple<I1,I2> &p)
90  {
91  *std_cxx1x::get<1>(p) = f (*std_cxx1x::get<0>(p));
92  }
93 
98  template <typename I1, typename I2, typename I3>
99  static
100  void
101  apply (const F &f,
102  const std_cxx1x::tuple<I1,I2,I3> &p)
103  {
104  *std_cxx1x::get<2>(p) = f (*std_cxx1x::get<0>(p),
105  *std_cxx1x::get<1>(p));
106  }
107 
112  template <typename I1, typename I2,
113  typename I3, typename I4>
114  static
115  void
116  apply (const F &f,
117  const std_cxx1x::tuple<I1,I2,I3,I4> &p)
118  {
119  *std_cxx1x::get<3>(p) = f (*std_cxx1x::get<0>(p),
120  *std_cxx1x::get<1>(p),
121  *std_cxx1x::get<2>(p));
122  }
123  };
124 
125 
135  template <typename F>
136  Body<F> make_body(const F &f)
137  {
138  return Body<F>(f);
139  }
140  }
141 
175  template <typename InputIterator,
176  typename OutputIterator,
177  typename Predicate>
178  void transform (const InputIterator &begin_in,
179  const InputIterator &end_in,
180  OutputIterator out,
181  Predicate &predicate,
182  const unsigned int grainsize)
183  {
184 #ifndef DEAL_II_WITH_THREADS
185  // make sure we don't get compiler
186  // warnings about unused arguments
187  (void) grainsize;
188 
189  for (OutputIterator in = begin_in; in != end_in;)
190  *out++ = predicate (*in++);
191 #else
192  typedef std_cxx1x::tuple<InputIterator,OutputIterator> Iterators;
193  typedef SynchronousIterators<Iterators> SyncIterators;
194  Iterators x_begin (begin_in, out);
195  Iterators x_end (end_in, OutputIterator());
196  tbb::parallel_for (tbb::blocked_range<SyncIterators>(x_begin,
197  x_end,
198  grainsize),
199  internal::make_body (predicate),
200  tbb::auto_partitioner());
201 #endif
202  }
203 
204 
205 
241  template <typename InputIterator1,
242  typename InputIterator2,
243  typename OutputIterator,
244  typename Predicate>
245  void transform (const InputIterator1 &begin_in1,
246  const InputIterator1 &end_in1,
247  InputIterator2 in2,
248  OutputIterator out,
249  Predicate &predicate,
250  const unsigned int grainsize)
251  {
252 #ifndef DEAL_II_WITH_THREADS
253  // make sure we don't get compiler
254  // warnings about unused arguments
255  (void) grainsize;
256 
257  for (OutputIterator in1 = begin_in1; in1 != end_in1;)
258  *out++ = predicate (*in1++, *in2++);
259 #else
260  typedef
261  std_cxx1x::tuple<InputIterator1,InputIterator2,OutputIterator>
262  Iterators;
263  typedef SynchronousIterators<Iterators> SyncIterators;
264  Iterators x_begin (begin_in1, in2, out);
265  Iterators x_end (end_in1, InputIterator2(), OutputIterator());
266  tbb::parallel_for (tbb::blocked_range<SyncIterators>(x_begin,
267  x_end,
268  grainsize),
269  internal::make_body (predicate),
270  tbb::auto_partitioner());
271 #endif
272  }
273 
274 
275 
309  template <typename InputIterator1,
310  typename InputIterator2,
311  typename InputIterator3,
312  typename OutputIterator,
313  typename Predicate>
314  void transform (const InputIterator1 &begin_in1,
315  const InputIterator1 &end_in1,
316  InputIterator2 in2,
317  InputIterator3 in3,
318  OutputIterator out,
319  Predicate &predicate,
320  const unsigned int grainsize)
321  {
322 #ifndef DEAL_II_WITH_THREADS
323  // make sure we don't get compiler
324  // warnings about unused arguments
325  (void) grainsize;
326 
327  for (OutputIterator in1 = begin_in1; in1 != end_in1;)
328  *out++ = predicate (*in1++, *in2++, *in3++);
329 #else
330  typedef
331  std_cxx1x::tuple<InputIterator1,InputIterator2,InputIterator3,OutputIterator>
332  Iterators;
333  typedef SynchronousIterators<Iterators> SyncIterators;
334  Iterators x_begin (begin_in1, in2, in3, out);
335  Iterators x_end (end_in1, InputIterator2(),
336  InputIterator3(), OutputIterator());
337  tbb::parallel_for (tbb::blocked_range<SyncIterators>(x_begin,
338  x_end,
339  grainsize),
340  internal::make_body (predicate),
341  tbb::auto_partitioner());
342 #endif
343  }
344 
345 
346  namespace internal
347  {
348 #ifdef DEAL_II_WITH_THREADS
349 
353  template <typename RangeType, typename Function>
354  void apply_to_subranges (const tbb::blocked_range<RangeType> &range,
355  const Function &f)
356  {
357  f (range.begin(), range.end());
358  }
359 #endif
360  }
361 
362 
463  template <typename RangeType, typename Function>
464  void apply_to_subranges (const RangeType &begin,
465  const typename identity<RangeType>::type &end,
466  const Function &f,
467  const unsigned int grainsize)
468  {
469 #ifndef DEAL_II_WITH_THREADS
470  // make sure we don't get compiler
471  // warnings about unused arguments
472  (void) grainsize;
473 
474  f (begin, end);
475 #else
476  tbb::parallel_for (tbb::blocked_range<RangeType>
477  (begin, end, grainsize),
478  std_cxx1x::bind (&internal::apply_to_subranges<RangeType,Function>,
479  std_cxx1x::_1,
480  std_cxx1x::cref(f)),
481  tbb::auto_partitioner());
482 #endif
483  }
484 
485 
486 
515  {
520  virtual ~ParallelForInteger ();
521 
533  void apply_parallel (const std::size_t begin,
534  const std::size_t end,
535  const std::size_t minimum_parallel_grain_size) const;
536 
546  virtual void apply_to_subrange (const std::size_t,
547  const std::size_t) const = 0;
548  };
549 
550 
551 
552  namespace internal
553  {
554 #ifdef DEAL_II_WITH_THREADS
555 
565  template <typename ResultType,
566  typename Function>
568  {
573  ResultType result;
574 
590  template <typename Reductor>
592  const Reductor &reductor,
593  const ResultType neutral_element = ResultType())
594  :
595  result (neutral_element),
596  f (f),
598  reductor (reductor)
599  {}
600 
606  tbb::split)
607  :
608  result (r.neutral_element),
609  f (r.f),
611  reductor (r.reductor)
612  {}
613 
619  void join (const ReductionOnSubranges &r)
620  {
621  result = reductor(result, r.result);
622  }
623 
628  template <typename RangeType>
629  void operator () (const tbb::blocked_range<RangeType> &range)
630  {
631  result = reductor(result,
632  f (range.begin(), range.end()));
633  }
634 
635  private:
640  const Function f;
641 
650  const ResultType neutral_element;
651 
657  const std_cxx1x::function<ResultType (ResultType, ResultType)> reductor;
658  };
659 #endif
660  }
661 
662 
743  template <typename ResultType, typename RangeType, typename Function>
744  ResultType accumulate_from_subranges (const Function &f,
745  const RangeType &begin,
746  const typename identity<RangeType>::type &end,
747  const unsigned int grainsize)
748  {
749 #ifndef DEAL_II_WITH_THREADS
750  // make sure we don't get compiler
751  // warnings about unused arguments
752  (void) grainsize;
753 
754  return f(begin,end);
755 #else
757  reductor (f, std::plus<ResultType>(), 0);
758  tbb::parallel_reduce (tbb::blocked_range<RangeType>(begin, end, grainsize),
759  reductor,
760  tbb::auto_partitioner());
761  return reductor.result;
762 #endif
763  }
764 
765 }
766 
767 
768 namespace internal
769 {
770  namespace Vector
771  {
797  extern unsigned int minimum_parallel_grain_size;
798  }
799 
800 
801  namespace SparseMatrix
802  {
810  extern unsigned int minimum_parallel_grain_size;
811  }
812 
813 } // end of namespace internal
814 
815 
816 /* --------------------------- inline functions ------------------------- */
817 
818 namespace parallel
819 {
820 
821 #ifdef DEAL_II_WITH_THREADS
822 
823  namespace internal
824  {
830  {
832  :
833  worker_ (worker)
834  {}
835 
836  void operator() (const tbb::blocked_range<std::size_t> &range) const
837  {
838  worker_.apply_to_subrange (range.begin(), range.end());
839  }
840 
841  const parallel::ParallelForInteger &worker_;
842  };
843  }
844 
845 #endif
846 
847 
848  inline
850  {}
851 
852 
853  inline
854  void
855  ParallelForInteger::apply_parallel (const std::size_t begin,
856  const std::size_t end,
857  const std::size_t minimum_parallel_grain_size) const
858  {
859 #ifndef DEAL_II_WITH_THREADS
860  // make sure we don't get compiler
861  // warnings about unused arguments
862  (void) minimum_parallel_grain_size;
863 
864  apply_to_subrange (begin, end);
865 #else
866  internal::ParallelForWrapper worker(*this);
867  tbb::parallel_for (tbb::blocked_range<std::size_t>
868  (begin, end, minimum_parallel_grain_size),
869  worker,
870  tbb::auto_partitioner());
871 #endif
872  }
873 
874 } // end of namespace parallel
875 
876 DEAL_II_NAMESPACE_CLOSE
877 
878 #endif
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:855
void join(const ReductionOnSubranges &r)
Definition: parallel.h:619
static void apply(const F &f, const std_cxx1x::tuple< I1, I2 > &p)
Definition: parallel.h:88
static void apply(const F &f, const std_cxx1x::tuple< I1, I2, I3 > &p)
Definition: parallel.h:101
void operator()(const tbb::blocked_range< RangeType > &range)
Definition: parallel.h:629
const std_cxx1x::function< ResultType(ResultType, ResultType)> reductor
Definition: parallel.h:657
void apply_to_subranges(const RangeType &begin, const typename identity< RangeType >::type &end, const Function &f, const unsigned int grainsize)
Definition: parallel.h:464
ReductionOnSubranges(const Function &f, const Reductor &reductor, const ResultType neutral_element=ResultType())
Definition: parallel.h:591
ReductionOnSubranges(const ReductionOnSubranges &r, tbb::split)
Definition: parallel.h:605
ResultType accumulate_from_subranges(const Function &f, const RangeType &begin, const typename identity< RangeType >::type &end, const unsigned int grainsize)
Definition: parallel.h:744
void transform(const InputIterator &begin_in, const InputIterator &end_in, OutputIterator out, Predicate &predicate, const unsigned int grainsize)
Definition: parallel.h:178
virtual void apply_to_subrange(const std::size_t, const std::size_t) const =0
static void apply(const F &f, const std_cxx1x::tuple< I1, I2, I3, I4 > &p)
Definition: parallel.h:116