include/deal.II/base/parallel.h

00001 //---------------------------------------------------------------------------
00002 //    @f$Id: parallel.h 25496 2012-05-06 07:20:25Z kronbichler @f$
00003 //
00004 //    Copyright (C) 2008, 2009, 2011, 2012 by the deal.II authors
00005 //
00006 //    This file is subject to QPL and may not be  distributed
00007 //    without copyright and license information. Please refer
00008 //    to the file deal.II/doc/license.html for the  text  and
00009 //    further information on this license.
00010 //
00011 //---------------------------------------------------------------------------
00012 #ifndef __deal2__parallel_h
00013 #define __deal2__parallel_h
00014 
00015 
00016 #include <deal.II/base/config.h>
00017 #include <deal.II/base/exceptions.h>
00018 #include <deal.II/base/template_constraints.h>
00019 #include <deal.II/base/synchronous_iterator.h>
00020 
00021 #include <deal.II/base/std_cxx1x/tuple.h>
00022 #include <deal.II/base/std_cxx1x/bind.h>
00023 #include <deal.II/base/std_cxx1x/function.h>
00024 
00025 #include <cstddef>
00026 
00027 #if DEAL_II_USE_MT == 1
00028 #  include <tbb/parallel_for.h>
00029 #  include <tbb/parallel_reduce.h>
00030 #  include <tbb/partitioner.h>
00031 #  include <tbb/blocked_range.h>
00032 #endif
00033 
00034 
00035 //TODO[WB]: allow calling functions to pass along a tbb::affinity_partitioner object to ensure that subsequent calls use the same cache lines
00036 
00037 DEAL_II_NAMESPACE_OPEN
00038 
00039 namespace parallel
00040 {
00041   namespace internal
00042   {
00049     template <typename F>
00050     struct Body
00051     {
00056         Body (const F &f)
00057                         :
00058                         f (f)
00059           {}
00060 
00061         template <typename Range>
00062         void
00063         operator () (const Range &range) const
00064           {
00065             for (typename Range::const_iterator p=range.begin();
00066                  p != range.end(); ++p)
00067               apply (f, p.iterators);
00068           }
00069 
00070       private:
00074         const F f;
00075 
00080         template <typename I1, typename I2>
00081         static
00082         void
00083         apply (const F &f,
00084                const std_cxx1x::tuple<I1,I2> &p)
00085           {
00086             *std_cxx1x::get<1>(p) = f (*std_cxx1x::get<0>(p));
00087           }
00088 
00093         template <typename I1, typename I2, typename I3>
00094         static
00095         void
00096         apply (const F &f,
00097                const std_cxx1x::tuple<I1,I2,I3> &p)
00098           {
00099             *std_cxx1x::get<2>(p) = f (*std_cxx1x::get<0>(p),
00100                                        *std_cxx1x::get<1>(p));
00101           }
00102 
00107         template <typename I1, typename I2,
00108                   typename I3, typename I4>
00109         static
00110         void
00111         apply (const F &f,
00112                const std_cxx1x::tuple<I1,I2,I3,I4> &p)
00113           {
00114             *std_cxx1x::get<3>(p) = f (*std_cxx1x::get<0>(p),
00115                                        *std_cxx1x::get<1>(p),
00116                                        *std_cxx1x::get<2>(p));
00117           }
00118     };
00119 
00120 
00130     template <typename F>
00131     Body<F> make_body(const F &f)
00132     {
00133       return Body<F>(f);
00134     }
00135   }
00136 
00170   template <typename InputIterator,
00171             typename OutputIterator,
00172             typename Predicate>
00173   void transform (const InputIterator &begin_in,
00174                   const InputIterator &end_in,
00175                   OutputIterator       out,
00176                   Predicate           &predicate,
00177                   const unsigned int   grainsize)
00178   {
00179 #if DEAL_II_USE_MT == 0
00180                                      // make sure we don't get compiler
00181                                      // warnings about unused arguments
00182     (void) grainsize;
00183 
00184     for (OutputIterator in = begin_in; in != end_in;)
00185       *out++ = predicate (*in++);
00186 #else
00187     typedef std_cxx1x::tuple<InputIterator,OutputIterator> Iterators;
00188     typedef SynchronousIterators<Iterators> SyncIterators;
00189     Iterators x_begin (begin_in, out);
00190     Iterators x_end (end_in, OutputIterator());
00191     tbb::parallel_for (tbb::blocked_range<SyncIterators>(x_begin,
00192                                                          x_end,
00193                                                          grainsize),
00194                        internal::make_body (predicate),
00195                        tbb::auto_partitioner());
00196 #endif
00197   }
00198 
00199 
00200 
00236   template <typename InputIterator1,
00237             typename InputIterator2,
00238             typename OutputIterator,
00239             typename Predicate>
00240   void transform (const InputIterator1 &begin_in1,
00241                   const InputIterator1 &end_in1,
00242                   InputIterator2        in2,
00243                   OutputIterator        out,
00244                   Predicate            &predicate,
00245                   const unsigned int    grainsize)
00246   {
00247 #if DEAL_II_USE_MT == 0
00248                                      // make sure we don't get compiler
00249                                      // warnings about unused arguments
00250     (void) grainsize;
00251 
00252     for (OutputIterator in1 = begin_in1; in1 != end_in1;)
00253       *out++ = predicate (*in1++, *in2++);
00254 #else
00255     typedef
00256       std_cxx1x::tuple<InputIterator1,InputIterator2,OutputIterator>
00257       Iterators;
00258     typedef SynchronousIterators<Iterators> SyncIterators;
00259     Iterators x_begin (begin_in1, in2, out);
00260     Iterators x_end (end_in1, InputIterator2(), OutputIterator());
00261     tbb::parallel_for (tbb::blocked_range<SyncIterators>(x_begin,
00262                                                          x_end,
00263                                                          grainsize),
00264                        internal::make_body (predicate),
00265                        tbb::auto_partitioner());
00266 #endif
00267   }
00268 
00269 
00270 
00304   template <typename InputIterator1,
00305             typename InputIterator2,
00306             typename InputIterator3,
00307             typename OutputIterator,
00308             typename Predicate>
00309   void transform (const InputIterator1 &begin_in1,
00310                   const InputIterator1 &end_in1,
00311                   InputIterator2        in2,
00312                   InputIterator3        in3,
00313                   OutputIterator        out,
00314                   Predicate            &predicate,
00315                   const unsigned int    grainsize)
00316   {
00317 #if DEAL_II_USE_MT == 0
00318                                      // make sure we don't get compiler
00319                                      // warnings about unused arguments
00320     (void) grainsize;
00321 
00322     for (OutputIterator in1 = begin_in1; in1 != end_in1;)
00323       *out++ = predicate (*in1++, *in2++, *in3++);
00324 #else
00325     typedef
00326       std_cxx1x::tuple<InputIterator1,InputIterator2,InputIterator3,OutputIterator>
00327       Iterators;
00328     typedef SynchronousIterators<Iterators> SyncIterators;
00329     Iterators x_begin (begin_in1, in2, in3, out);
00330     Iterators x_end (end_in1, InputIterator2(),
00331                      InputIterator3(), OutputIterator());
00332     tbb::parallel_for (tbb::blocked_range<SyncIterators>(x_begin,
00333                                                          x_end,
00334                                                          grainsize),
00335                        internal::make_body (predicate),
00336                        tbb::auto_partitioner());
00337 #endif
00338   }
00339 
00340 
00341   namespace internal
00342   {
00343 #if DEAL_II_USE_MT == 1
00344 
00348     template <typename RangeType, typename Function>
00349     void apply_to_subranges (const tbb::blocked_range<RangeType> &range,
00350                              const Function  &f)
00351     {
00352       f (range.begin(), range.end());
00353     }
00354 #endif
00355   }
00356 
00357 
00458   template <typename RangeType, typename Function>
00459   void apply_to_subranges (const RangeType                          &begin,
00460                            const typename identity<RangeType>::type &end,
00461                            const Function                           &f,
00462                            const unsigned int                        grainsize)
00463   {
00464 #if DEAL_II_USE_MT == 0
00465                                      // make sure we don't get compiler
00466                                      // warnings about unused arguments
00467     (void) grainsize;
00468 
00469     f (begin, end);
00470 #else
00471     tbb::parallel_for (tbb::blocked_range<RangeType>
00472                        (begin, end, grainsize),
00473                        std_cxx1x::bind (&internal::apply_to_subranges<RangeType,Function>,
00474                                         std_cxx1x::_1,
00475                                         std_cxx1x::cref(f)),
00476                        tbb::auto_partitioner());
00477 #endif
00478   }
00479 
00480 
00481 
00509   struct ParallelForInteger
00510   {
00515       virtual ~ParallelForInteger ();
00516 
00528     void apply_parallel (const std::size_t begin,
00529                          const std::size_t end,
00530                          const std::size_t minimum_parallel_grain_size) const;
00531 
00541     virtual void apply_to_subrange (const std::size_t,
00542                                     const std::size_t) const = 0;
00543   };
00544 
00545 
00546 
00547   namespace internal
00548   {
00549 #if DEAL_II_USE_MT == 1
00550 
00560     template <typename ResultType,
00561               typename Function>
00562     struct ReductionOnSubranges
00563     {
00568         ResultType result;
00569 
00585         template <typename Reductor>
00586         ReductionOnSubranges (const Function &f,
00587                               const Reductor &reductor,
00588                               const ResultType neutral_element = ResultType())
00589                         :
00590                         result (neutral_element),
00591                         f (f),
00592                         neutral_element (neutral_element),
00593                         reductor (reductor)
00594           {}
00595 
00600         ReductionOnSubranges (const ReductionOnSubranges &r,
00601                               tbb::split)
00602                         :
00603                         result (r.neutral_element),
00604                         f (r.f),
00605                         neutral_element (r.neutral_element),
00606                         reductor (r.reductor)
00607           {}
00608 
00614         void join (const ReductionOnSubranges &r)
00615           {
00616             result = reductor(result, r.result);
00617           }
00618 
00623         template <typename RangeType>
00624         void operator () (const tbb::blocked_range<RangeType> &range)
00625           {
00626             result = reductor(result,
00627                               f (range.begin(), range.end()));
00628           }
00629 
00630       private:
00635         const Function f;
00636 
00645         const ResultType neutral_element;
00646 
00652         const std_cxx1x::function<ResultType (ResultType, ResultType)> reductor;
00653     };
00654 #endif
00655   }
00656 
00657 
00738   template <typename ResultType, typename RangeType, typename Function>
00739   ResultType accumulate_from_subranges (const Function &f,
00740                                         const RangeType                          &begin,
00741                                         const typename identity<RangeType>::type &end,
00742                                         const unsigned int grainsize)
00743   {
00744 #if DEAL_II_USE_MT == 0
00745                                      // make sure we don't get compiler
00746                                      // warnings about unused arguments
00747     (void) grainsize;
00748 
00749     return f(begin,end);
00750 #else
00751     internal::ReductionOnSubranges<ResultType,Function>
00752       reductor (f, std::plus<ResultType>(), 0);
00753     tbb::parallel_reduce (tbb::blocked_range<RangeType>(begin, end, grainsize),
00754                           reductor,
00755                           tbb::auto_partitioner());
00756     return reductor.result;
00757 #endif
00758   }
00759 
00760 }
00761 
00762 
00763 namespace internal
00764 {
00765   namespace Vector
00766   {
00792     extern unsigned int minimum_parallel_grain_size;
00793   }
00794 
00795 
00796   namespace SparseMatrix
00797   {
00805     extern unsigned int minimum_parallel_grain_size;
00806   }
00807 
00808 } // end of namespace internal
00809 
00810 
00811 /* --------------------------- inline functions ------------------------- */
00812 
00813 namespace parallel
00814 {
00815 
00816 #if DEAL_II_USE_MT == 1
00817 
00818   namespace internal
00819   {
00824     struct ParallelForWrapper
00825     {
00826       ParallelForWrapper (const parallel::ParallelForInteger &worker)
00827         :
00828         worker_ (worker)
00829       {}
00830 
00831       void operator() (const tbb::blocked_range<std::size_t> &range) const
00832       {
00833         worker_.apply_to_subrange (range.begin(), range.end());
00834       }
00835 
00836       const parallel::ParallelForInteger &worker_;
00837     };
00838   }
00839 
00840 #endif
00841 
00842 
00843   inline
00844   ParallelForInteger::~ParallelForInteger ()
00845   {}
00846 
00847 
00848   inline
00849   void
00850   ParallelForInteger::apply_parallel (const std::size_t begin,
00851                                       const std::size_t end,
00852                                       const std::size_t minimum_parallel_grain_size) const
00853   {
00854 #if DEAL_II_USE_MT == 0
00855                                      // make sure we don't get compiler
00856                                      // warnings about unused arguments
00857     (void) minimum_parallel_grain_size;
00858 
00859     apply_to_subrange (begin, end);
00860 #else
00861     internal::ParallelForWrapper worker(*this);
00862     tbb::parallel_for (tbb::blocked_range<std::size_t>
00863                        (begin, end, minimum_parallel_grain_size),
00864                        worker,
00865                        tbb::auto_partitioner());
00866 #endif
00867   }
00868 
00869 } // end of namespace parallel
00870 
00871 DEAL_II_NAMESPACE_CLOSE
00872 
00873 #endif
00874 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

deal.II documentation generated on Tue May 22 2012 12:06:02 by doxygen 1.7.3