From f502e1ea16bee96d0326b4ccf22c66b7e59beed3 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Wed, 1 Mar 2017 08:11:30 +0100 Subject: [PATCH] extend internal::VectorOperations::parallel_for() to [start,end) --- .../deal.II/lac/vector_operations_internal.h | 28 ++++--- ...ector_operations_parallel_for_start_end.cc | 80 +++++++++++++++++++ ...r_operations_parallel_for_start_end.output | 2 + 3 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 tests/lac/vector_operations_parallel_for_start_end.cc create mode 100644 tests/lac/vector_operations_parallel_for_start_end.output diff --git a/include/deal.II/lac/vector_operations_internal.h b/include/deal.II/lac/vector_operations_internal.h index 57a2cf0601..2947443272 100644 --- a/include/deal.II/lac/vector_operations_internal.h +++ b/include/deal.II/lac/vector_operations_internal.h @@ -116,11 +116,14 @@ namespace internal struct TBBForFunctor { TBBForFunctor(Functor &functor, - const size_type vec_size) + const size_type start, + const size_type end) : functor(functor), - vec_size(vec_size) + start(start), + end(end) { + const size_type vec_size = end-start; // set chunk size for sub-tasks const unsigned int gs = internal::Vector::minimum_parallel_grain_size; n_chunks = std::min(static_cast(4*MultithreadInfo::n_threads()), @@ -140,13 +143,14 @@ namespace internal void operator() (const tbb::blocked_range &range) const { - const size_type begin = range.begin()*chunk_size; - const size_type end = std::min(range.end()*chunk_size, vec_size); - functor(begin, end); + const size_type r_begin = start + range.begin()*chunk_size; + const size_type r_end = std::min(start + range.end()*chunk_size, end); + functor(r_begin, r_end); } Functor &functor; - const size_type vec_size; + const size_type start; + const size_type end; unsigned int n_chunks; size_type chunk_size; }; @@ -154,9 +158,11 @@ namespace internal template void parallel_for(Functor &functor, - size_type vec_size, - std_cxx11::shared_ptr &partitioner) + size_type end, + std_cxx11::shared_ptr &partitioner, + size_type start = 0) { + size_type vec_size = end-start; #ifdef DEAL_II_WITH_THREADS // only go to the parallel function in case there are at least 4 parallel // items, otherwise the overhead is too large @@ -169,7 +175,7 @@ namespace internal std_cxx11::shared_ptr tbb_partitioner = partitioner->acquire_one_partitioner(); - TBBForFunctor generic_functor(functor, vec_size); + TBBForFunctor generic_functor(functor, start, end); tbb::parallel_for (tbb::blocked_range (0, generic_functor.n_chunks, 1), @@ -178,9 +184,9 @@ namespace internal partitioner->release_one_partitioner(tbb_partitioner); } else if (vec_size > 0) - functor(0,vec_size); + functor(start,end); #else - functor(0,vec_size); + functor(start,end); (void)partitioner; #endif } diff --git a/tests/lac/vector_operations_parallel_for_start_end.cc b/tests/lac/vector_operations_parallel_for_start_end.cc new file mode 100644 index 0000000000..d7965dbca4 --- /dev/null +++ b/tests/lac/vector_operations_parallel_for_start_end.cc @@ -0,0 +1,80 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2012 - 2015 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + + +// check that internal::VectorOperations::parallel_for works for start-end + +#include "../tests.h" +#include +#include +#include +#include +#include +#include + + + + +template +void check () +{ + for (unsigned int test=0; test<5; ++test) + { + const unsigned int size = 17 + test*1101; + + std_cxx11::shared_ptr< ::dealii::parallel::internal::TBBPartitioner> thread_loop_partitioner; + thread_loop_partitioner.reset(new ::dealii::parallel::internal::TBBPartitioner()); + + Number *val; + Utilities::System::posix_memalign ((void **)&val, 64, sizeof(Number)*size); + + const Number s = 3.1415; + internal::VectorOperations::Vector_set setter(s, val); + + // now break the size in chunks + const unsigned int n_chunks = 3; + const unsigned int chunk_size = size / n_chunks; + for (unsigned int i = 0; i <= n_chunks; ++i) + { + const unsigned int begin = i*chunk_size; + const unsigned int end = std::min((i+1)*chunk_size, size); + internal::VectorOperations::parallel_for(setter, end, + thread_loop_partitioner, + begin); + } + + // check values: + for (unsigned int i = 0; i < size; ++i) + AssertThrow(val[i] == s, + ExcInternalError()); + + free(val); + } +} + + +int main() +{ + std::ofstream logfile("output"); + deallog << std::fixed; + deallog << std::setprecision(2); + deallog.attach(logfile); + deallog.threshold_double(1.e-10); + + check(); + check(); + check(); + deallog << "OK" << std::endl; +} diff --git a/tests/lac/vector_operations_parallel_for_start_end.output b/tests/lac/vector_operations_parallel_for_start_end.output new file mode 100644 index 0000000000..0fd8fc12f0 --- /dev/null +++ b/tests/lac/vector_operations_parallel_for_start_end.output @@ -0,0 +1,2 @@ + +DEAL::OK -- 2.39.5