]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Cleanup the Vector::thread_loop_partitioner logic. 7683/head
authorDavid Wells <drwells@email.unc.edu>
Mon, 4 Feb 2019 03:35:36 +0000 (22:35 -0500)
committerDavid Wells <drwells@email.unc.edu>
Tue, 5 Feb 2019 00:31:25 +0000 (19:31 -0500)
It was previously possible to, in one function call, either set up the
partitioner multiple times or for inappropriately small vectors. This
commit cleans up the way we handle the partitioner in multiple places so
that, when possible, vectors share partitioners and do not set up
partitioners if they are too small.

include/deal.II/lac/vector.h
include/deal.II/lac/vector.templates.h

index 2dadf1da5e10b66d873a3d6e6ac85399af3ac110..b413f686b1293ffd468029462503fd72f3f78bec 100644 (file)
@@ -986,6 +986,22 @@ private:
    */
   AlignedVector<Number> values;
 
+  /**
+   * Convenience function used at the end of initialization or
+   * reinitialization. Resets (if necessary) the loop partitioner to the
+   * correct state, based on its current state and the length of the vector.
+   */
+  void
+  maybe_reset_thread_partitioner();
+
+  /**
+   * Actual implementation of the reinit functions.
+   */
+  void
+  do_reinit(const size_type new_size,
+            const bool      omit_zeroing_entries,
+            const bool      reset_partitioner);
+
   /**
    * For parallel loops with TBB, this member variable stores the affinity
    * information of loops.
@@ -1275,7 +1291,8 @@ template <typename Number>
 inline void
 Vector<Number>::swap(Vector<Number> &v)
 {
-  std::swap(values, v.values);
+  values.swap(v.values);
+  std::swap(thread_loop_partitioner, v.thread_loop_partitioner);
 }
 
 
@@ -1300,6 +1317,7 @@ Vector<Number>::load(Archive &ar, const unsigned int)
   // the load stuff again from the archive
   ar &static_cast<Subscriptor &>(*this);
   ar &values;
+  maybe_reset_thread_partitioner();
 }
 
 #endif
index 87c126c8b8b4a25cc1e1aad3c1b74ea73bcfea00..bc98f73050e57358d13cbcc7289e51056f9637b1 100644 (file)
@@ -83,6 +83,11 @@ namespace internal
   copy_petsc_vector(const PETScWrappers::VectorBase &v,
                     ::dealii::Vector<Number> &       out)
   {
+    if (v.size() == 0)
+      {
+        out.reinit(0);
+        return;
+      }
     // Create a sequential PETSc vector and then copy over the entries into
     // the deal.II vector.
     Vec        sequential_vector;
@@ -125,10 +130,7 @@ namespace internal
 template <typename Number>
 Vector<Number>::Vector(const PETScWrappers::VectorBase &v)
 {
-  if (v.size() != 0)
-    {
-      internal::copy_petsc_vector(v, *this);
-    }
+  internal::copy_petsc_vector(v, *this);
 }
 #endif
 
@@ -164,6 +166,8 @@ Vector<Number>::Vector(const TrilinosWrappers::MPI::Vector &v)
       AssertThrow(ierr == 0, ExcTrilinosError(ierr));
 
       std::copy(start_ptr[0], start_ptr[0] + size(), begin());
+
+      maybe_reset_thread_partitioner();
     }
 }
 
@@ -177,7 +181,6 @@ Vector<Number>::operator=(const Vector<Number> &v)
   if (PointerComparison::equal(this, &v))
     return *this;
 
-  thread_loop_partitioner = v.thread_loop_partitioner;
   if (size() != v.size())
     reinit(v, true);
 
@@ -201,7 +204,6 @@ template <typename Number2>
 inline Vector<Number> &
 Vector<Number>::operator=(const Vector<Number2> &v)
 {
-  thread_loop_partitioner = v.thread_loop_partitioner;
   if (size() != v.size())
     reinit(v, true);
 
@@ -221,41 +223,7 @@ template <typename Number>
 inline void
 Vector<Number>::reinit(const size_type n, const bool omit_zeroing_entries)
 {
-  const std::size_t old_size = size();
-
-  // avoid allocating if the new size is not larger than the old size
-  if (n <= size())
-    {
-      thread_loop_partitioner =
-        std::make_shared<parallel::internal::TBBPartitioner>();
-      if (n == 0)
-        {
-          values.clear();
-        }
-      else if (n != size())
-        values.resize_fast(n);
-
-      if (!omit_zeroing_entries)
-        values.fill();
-      return;
-    }
-
-  // otherwise size() < n and we must allocate
-  AlignedVector<Number> new_values;
-  new_values.resize_fast(n);
-  if (!omit_zeroing_entries)
-    new_values.fill();
-  new_values.swap(values);
-
-  if (old_size != size())
-    {
-      // only reset the partitioner if we actually expect a significant vector
-      // size
-      if (size() >=
-          4 * internal::VectorImplementation::minimum_parallel_grain_size)
-        thread_loop_partitioner =
-          std::make_shared<parallel::internal::TBBPartitioner>();
-    }
+  do_reinit(n, omit_zeroing_entries, true);
 }
 
 
@@ -264,26 +232,9 @@ template <typename Number>
 inline void
 Vector<Number>::grow_or_shrink(const size_type n)
 {
-  const std::size_t old_size = size();
-  if (n == 0)
-    {
-      values.clear();
-      thread_loop_partitioner =
-        std::make_shared<parallel::internal::TBBPartitioner>();
-      return;
-    }
-
   values.resize(n);
 
-  if (old_size != n)
-    {
-      // only reset the partitioner if we actually expect a significant vector
-      // size
-      if (size() >=
-          4 * internal::VectorImplementation::minimum_parallel_grain_size)
-        thread_loop_partitioner =
-          std::make_shared<parallel::internal::TBBPartitioner>();
-    }
+  maybe_reset_thread_partitioner();
 }
 
 
@@ -294,9 +245,8 @@ void
 Vector<Number>::reinit(const Vector<Number2> &v,
                        const bool             omit_zeroing_entries)
 {
+  do_reinit(v.size(), omit_zeroing_entries, false);
   thread_loop_partitioner = v.thread_loop_partitioner;
-
-  reinit(v.size(), omit_zeroing_entries);
 }
 
 
@@ -1046,6 +996,57 @@ Vector<Number>::memory_consumption() const
 }
 
 
+
+template <typename Number>
+void
+Vector<Number>::maybe_reset_thread_partitioner()
+{
+  if (size() >= 4 * internal::VectorImplementation::minimum_parallel_grain_size)
+    {
+      if (thread_loop_partitioner == nullptr)
+        thread_loop_partitioner =
+          std::make_shared<parallel::internal::TBBPartitioner>();
+    }
+  else
+    thread_loop_partitioner.reset();
+}
+
+
+
+template <typename Number>
+void
+Vector<Number>::do_reinit(const size_type new_size,
+                          const bool      omit_zeroing_entries,
+                          const bool      reset_partitioner)
+{
+  if (new_size <= size())
+    {
+      if (new_size == 0)
+        {
+          values.clear();
+        }
+      else
+        {
+          values.resize_fast(new_size);
+          if (!omit_zeroing_entries)
+            values.fill();
+        }
+    }
+  else
+    {
+      // otherwise size() < new_size and we must allocate
+      AlignedVector<Number> new_values;
+      new_values.resize_fast(new_size);
+      if (!omit_zeroing_entries)
+        new_values.fill();
+      new_values.swap(values);
+    }
+
+  if (reset_partitioner)
+    maybe_reset_thread_partitioner();
+}
+
+
 DEAL_II_NAMESPACE_CLOSE
 
 #endif

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.