From e31acc96a49f2e190d8d5dc4ba8397826852e2ce Mon Sep 17 00:00:00 2001 From: Martin Kronbichler Date: Thu, 14 Apr 2016 17:49:57 +0200 Subject: [PATCH] Do not change partitioners in reinit(n), cleanup code --- include/deal.II/base/parallel.h | 46 ++++++++++++----- include/deal.II/lac/vector.h | 4 +- include/deal.II/lac/vector.templates.h | 69 ++++++++++++++------------ source/lac/vector.inst.in | 3 +- 4 files changed, 75 insertions(+), 47 deletions(-) diff --git a/include/deal.II/base/parallel.h b/include/deal.II/base/parallel.h index 2aeab248b3..8ac954ab13 100644 --- a/include/deal.II/base/parallel.h +++ b/include/deal.II/base/parallel.h @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -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 + acquire_one_partitioner() { dealii::Threads::Mutex::ScopedLock lock(mutex); if (in_use) - return NULL; + return std_cxx11::shared_ptr(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 &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 my_partitioner; /** * A flag to indicate whether the partitioner has been acquired but not diff --git a/include/deal.II/lac/vector.h b/include/deal.II/lac/vector.h index fea7f5a1ec..d87c63e26b 100644 --- a/include/deal.II/lac/vector.h +++ b/include/deal.II/lac/vector.h @@ -1040,7 +1040,9 @@ Vector::Vector () vec_size(0), max_vec_size(0), val(0) -{} +{ + reinit(0); +} diff --git a/include/deal.II/lac/vector.templates.h b/include/deal.II/lac/vector.templates.h index aff70219c6..a27d46b131 100644 --- a/include/deal.II/lac/vector.templates.h +++ b/include/deal.II/lac/vector.templates.h @@ -121,7 +121,7 @@ namespace internal template void vectorized_transform(Functor &functor, size_type vec_size, - parallel::internal::TBBPartitioner *partitioner = NULL) + std_cxx11::shared_ptr &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_partitioner = + partitioner->acquire_one_partitioner(); tbb::parallel_for (tbb::blocked_range (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::operator= (const Vector &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 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 & Vector::operator= (const Vector &v) { + thread_loop_partitioner = v.thread_loop_partitioner; if (vec_size != v.vec_size) reinit (v, true); dealii::internal::Vector_copy 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::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::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(0); } @@ -952,7 +957,7 @@ Vector::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 &Vector::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::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::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 &Vector::operator -= (const Vector &v) internal::Vectorization_subtract_v 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::add (const Number v) internal::Vectorization_add_factor 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::add (const Vector &v) internal::Vectorization_add_v 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::add (const Number a, const Vector &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::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::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::scale (const Vector &s) internal::Vectorization_scale 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::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::equ (const Number a, const Vector &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::equ (const Number a, const Vector &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::ratio (const Vector &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); } diff --git a/source/lac/vector.inst.in b/source/lac/vector.inst.in index 34078f5d90..87af5f9299 100644 --- a/source/lac/vector.inst.in +++ b/source/lac/vector.inst.in @@ -55,4 +55,5 @@ for (S1: REAL_SCALARS; S2: COMPLEX_SCALARS) { template Vector& Vector::operator= (const Vector &); - } \ No newline at end of file + } + -- 2.39.5