]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Do not change partitioners in reinit(n), cleanup code
authorMartin Kronbichler <kronbichler@lnm.mw.tum.de>
Thu, 14 Apr 2016 15:49:57 +0000 (17:49 +0200)
committerMartin Kronbichler <kronbichler@lnm.mw.tum.de>
Sat, 16 Apr 2016 13:31:22 +0000 (15:31 +0200)
include/deal.II/base/parallel.h
include/deal.II/lac/vector.h
include/deal.II/lac/vector.templates.h
source/lac/vector.inst.in

index 2aeab248b3c6cc196a622c73084e35108bc8c002..8ac954ab138b5d2956568079946c8c6c346691a1 100644 (file)
@@ -26,6 +26,7 @@
 #include <deal.II/base/std_cxx11/tuple.h>
 #include <deal.II/base/std_cxx11/bind.h>
 #include <deal.II/base/std_cxx11/function.h>
+#include <deal.II/base/std_cxx11/shared_ptr.h>
 
 #include <cstddef>
 
@@ -707,41 +708,60 @@ namespace parallel
       TBBPartitioner()
 #ifdef DEAL_II_WITH_THREADS
         :
+        my_partitioner(new tbb::affinity_partitioner()),
         in_use(false)
 #endif
       {}
 
 #ifdef DEAL_II_WITH_THREADS
       /**
-       * Return a pointer to the affinity partitioner in case it is free. If
-       * it is already in use (i.e., someone else called acquire without
-       * releasing it afterwards), the null pointer is returned.
+       * Destructor. Check that the object is not in use any more, i.e., all
+       * loops have been completed.
        */
-      tbb::affinity_partitioner *acquire()
+      ~TBBPartitioner()
+      {
+        Assert(in_use == false,
+               ExcInternalError("A vector partitioner goes out of scope, but "
+                                "it appears to be still in use."));
+      }
+
+      /**
+       * Return an affinity partitioner. In case the partitioner owned by the
+       * class is free, it is returned here. In case another thread has not
+       * released it yet, a new object is created. To free the partitioner
+       * again, return it by the release_one_partitioner() call.
+       */
+      std_cxx11::shared_ptr<tbb::affinity_partitioner>
+      acquire_one_partitioner()
       {
         dealii::Threads::Mutex::ScopedLock lock(mutex);
         if (in_use)
-          return NULL;
+          return std_cxx11::shared_ptr<tbb::affinity_partitioner>(new tbb::affinity_partitioner());
 
         in_use = true;
-        return &partitioner;
+        return my_partitioner;
       }
 
       /**
-       * After using the partitioner in a tbb loop through acquire(), this
-       * call makes the partitioner available again.
+       * After using the partitioner in a tbb loop through
+       * acquire_one_partitioner(), this call makes the partitioner available
+       * again.
        */
-      void release()
+      void release_one_partitioner(std_cxx11::shared_ptr<tbb::affinity_partitioner> &p)
       {
-        dealii::Threads::Mutex::ScopedLock lock(mutex);
-        in_use = false;
+        if (p.get() == my_partitioner.get())
+          {
+            dealii::Threads::Mutex::ScopedLock lock(mutex);
+            in_use = false;
+          }
       }
 
     private:
       /**
-       * The stored partitioner
+       * The stored partitioner that can accumulate knowledge over several
+       * runs of tbb::parallel_for
        */
-      tbb::affinity_partitioner partitioner;
+      std_cxx11::shared_ptr<tbb::affinity_partitioner> my_partitioner;
 
       /**
        * A flag to indicate whether the partitioner has been acquired but not
index fea7f5a1ec7213872eb5960b733d353e7ff808f5..d87c63e26b0d4a6fe52f1ebfa032753439246235 100644 (file)
@@ -1040,7 +1040,9 @@ Vector<Number>::Vector ()
   vec_size(0),
   max_vec_size(0),
   val(0)
-{}
+{
+  reinit(0);
+}
 
 
 
index aff70219c6764011b06d7b5d967a88ef9b0333a6..a27d46b131b67404e1ed0728553c9d587a3916dd 100644 (file)
@@ -121,7 +121,7 @@ namespace internal
   template <typename Functor>
   void vectorized_transform(Functor &functor,
                             size_type vec_size,
-                            parallel::internal::TBBPartitioner *partitioner = NULL)
+                            std_cxx11::shared_ptr<parallel::internal::TBBPartitioner> &partitioner)
   {
 #ifdef DEAL_II_WITH_THREADS
     // only go to the parallel function in case there are at least 4 parallel
@@ -129,23 +129,17 @@ namespace internal
     if (vec_size >= 4*internal::Vector::minimum_parallel_grain_size &&
         MultithreadInfo::n_threads() > 1)
       {
-        // in case the partitioner was used by another thread, create a
-        // private partitioner here for use in the loop (we could also use the
-        // auto partitioner of TBB but that increases code size considerably
-        // without major benefit)
-        tbb::affinity_partitioner *tbb_partitioner = (partitioner == NULL) ?
-                                                     NULL : partitioner->acquire();
-        tbb::affinity_partitioner private_partitioner;
-        if (tbb_partitioner == NULL)
-          tbb_partitioner = &private_partitioner;
+        if (partitioner.get() == NULL)
+          partitioner.reset(new parallel::internal::TBBPartitioner());
+        std_cxx11::shared_ptr<tbb::affinity_partitioner> tbb_partitioner =
+          partitioner->acquire_one_partitioner();
 
         tbb::parallel_for (tbb::blocked_range<size_type> (0,
                                                           vec_size,
                                                           internal::Vector::minimum_parallel_grain_size),
                            functor,
                            *tbb_partitioner);
-        if (partitioner != NULL)
-          partitioner->release();
+        partitioner->release_one_partitioner(tbb_partitioner);
       }
     else if (vec_size > 0)
       functor(0,vec_size);
@@ -798,13 +792,14 @@ Vector<Number>::operator= (const Vector<Number> &v)
   if (PointerComparison::equal(this, &v))
     return *this;
 
+  thread_loop_partitioner = v.thread_loop_partitioner;
   if (vec_size != v.vec_size)
     reinit (v, true);
 
   dealii::internal::Vector_copy<Number,Number> copier;
   copier.dst = val;
   copier.src = v.val;
-  internal::vectorized_transform(copier,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(copier,vec_size,thread_loop_partitioner);
 
   return *this;
 }
@@ -842,13 +837,14 @@ inline
 Vector<Number> &
 Vector<Number>::operator= (const Vector<Number2> &v)
 {
+  thread_loop_partitioner = v.thread_loop_partitioner;
   if (vec_size != v.vec_size)
     reinit (v, true);
 
   dealii::internal::Vector_copy<Number,Number2> copier;
   copier.dst = val;
   copier.src = v.val;
-  internal::vectorized_transform(copier,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(copier,vec_size,thread_loop_partitioner);
 
   return *this;
 }
@@ -860,12 +856,12 @@ inline
 void Vector<Number>::reinit (const size_type n,
                              const bool omit_zeroing_entries)
 {
-  thread_loop_partitioner.reset();
   if (n==0)
     {
       if (val) deallocate();
       val = 0;
       max_vec_size = vec_size = 0;
+      thread_loop_partitioner.reset(new parallel::internal::TBBPartitioner());
       return;
     };
 
@@ -875,8 +871,17 @@ void Vector<Number>::reinit (const size_type n,
       max_vec_size = n;
       allocate();
     };
-  vec_size = n;
-  thread_loop_partitioner.reset(new parallel::internal::TBBPartitioner());
+
+  if (vec_size != n)
+    {
+      vec_size = n;
+
+      // only reset the partitioner if we actually expect a significant vector
+      // size
+      if (vec_size > 4*internal::Vector::minimum_parallel_grain_size)
+        thread_loop_partitioner.reset(new parallel::internal::TBBPartitioner());
+    }
+
   if (omit_zeroing_entries == false)
     *this = static_cast<Number>(0);
 }
@@ -952,7 +957,7 @@ Vector<Number>::operator= (const Number s)
   setter.dst = val;
   setter.value = s;
 
-  internal::vectorized_transform(setter,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(setter,vec_size,thread_loop_partitioner);
 
   return *this;
 }
@@ -987,7 +992,7 @@ Vector<Number> &Vector<Number>::operator *= (const Number factor)
   vector_multiply.val = val;
   vector_multiply.factor = factor;
 
-  internal::vectorized_transform(vector_multiply,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_multiply,vec_size,thread_loop_partitioner);
 
   return *this;
 }
@@ -1008,7 +1013,7 @@ Vector<Number>::add (const Number a,
   vector_add_av.val = val;
   vector_add_av.v_val = v.val;
   vector_add_av.factor = a;
-  internal::vectorized_transform(vector_add_av,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_add_av,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1030,7 +1035,7 @@ Vector<Number>::sadd (const Number x,
   vector_sadd_xav.v_val = v.val;
   vector_sadd_xav.a = a;
   vector_sadd_xav.x = x;
-  internal::vectorized_transform(vector_sadd_xav,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_sadd_xav,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1646,7 +1651,7 @@ Vector<Number> &Vector<Number>::operator -= (const Vector<Number> &v)
   internal::Vectorization_subtract_v<Number> vector_subtract;
   vector_subtract.val = val;
   vector_subtract.v_val = v.val;
-  internal::vectorized_transform(vector_subtract,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_subtract,vec_size,thread_loop_partitioner);
 
   return *this;
 }
@@ -1661,7 +1666,7 @@ void Vector<Number>::add (const Number v)
   internal::Vectorization_add_factor<Number> vector_add;
   vector_add.val = val;
   vector_add.factor = v;
-  internal::vectorized_transform(vector_add,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_add,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1675,7 +1680,7 @@ void Vector<Number>::add (const Vector<Number> &v)
   internal::Vectorization_add_v<Number> vector_add;
   vector_add.val = val;
   vector_add.v_val = v.val;
-  internal::vectorized_transform(vector_add,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_add,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1697,7 +1702,7 @@ void Vector<Number>::add (const Number a, const Vector<Number> &v,
   vector_add.w_val = w.val;
   vector_add.a = a;
   vector_add.b = b;
-  internal::vectorized_transform(vector_add,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_add,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1715,7 +1720,7 @@ void Vector<Number>::sadd (const Number x,
   vector_sadd.val = val;
   vector_sadd.v_val = v.val;
   vector_sadd.x = x;
-  internal::vectorized_transform(vector_sadd,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_sadd,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1740,7 +1745,7 @@ void Vector<Number>::sadd (const Number x, const Number a,
   vector_sadd.x = x;
   vector_sadd.a = a;
   vector_sadd.b = b;
-  internal::vectorized_transform(vector_sadd,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_sadd,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1765,7 +1770,7 @@ void Vector<Number>::scale (const Vector<Number> &s)
   internal::Vectorization_scale<Number> vector_scale;
   vector_scale.val = val;
   vector_scale.v_val = s.val;
-  internal::vectorized_transform(vector_scale,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_scale,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1796,7 +1801,7 @@ void Vector<Number>::equ (const Number a,
   vector_equ.val = val;
   vector_equ.u_val = u.val;
   vector_equ.a = a;
-  internal::vectorized_transform(vector_equ,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_equ,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1840,7 +1845,7 @@ void Vector<Number>::equ (const Number a, const Vector<Number> &u,
   vector_equ.v_val = v.val;
   vector_equ.a = a;
   vector_equ.b = b;
-  internal::vectorized_transform(vector_equ,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_equ,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1862,7 +1867,7 @@ void Vector<Number>::equ (const Number a, const Vector<Number> &u,
   vector_equ.a = a;
   vector_equ.b = b;
   vector_equ.c = c;
-  internal::vectorized_transform(vector_equ,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_equ,vec_size,thread_loop_partitioner);
 }
 
 
@@ -1882,7 +1887,7 @@ void Vector<Number>::ratio (const Vector<Number> &a,
   vector_ratio.val = val;
   vector_ratio.a_val = a.val;
   vector_ratio.b_val = b.val;
-  internal::vectorized_transform(vector_ratio,vec_size,thread_loop_partitioner.get());
+  internal::vectorized_transform(vector_ratio,vec_size,thread_loop_partitioner);
 }
 
 
index 34078f5d90d8bfebcbdd026e6c4e25bc0f967c69..87af5f9299a06be730916efd8b47c7b930b77b47 100644 (file)
@@ -55,4 +55,5 @@ for (S1: REAL_SCALARS; S2: COMPLEX_SCALARS)
   {
     template
       Vector<S2>& Vector<S2>::operator=<S1> (const Vector<S1> &);
-  }
\ No newline at end of file
+  }
+

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.