From 87c41574ab2aab5052d0a84fe2ffb52e851ecde0 Mon Sep 17 00:00:00 2001 From: Jean-Paul Pelteret Date: Thu, 2 May 2019 19:32:10 +0200 Subject: [PATCH] Implement iterator range support in WorkStream::run() --- .../changes/minor/20190502Jean-PaulPelteret-1 | 5 + include/deal.II/base/work_stream.h | 171 ++++++++++++++++++ tests/base/work_stream_01a.cc | 72 ++++++++ tests/base/work_stream_01a.output | 21 +++ tests/base/work_stream_01b.cc | 82 +++++++++ tests/base/work_stream_01b.output | 21 +++ 6 files changed, 372 insertions(+) create mode 100644 doc/news/changes/minor/20190502Jean-PaulPelteret-1 create mode 100644 tests/base/work_stream_01a.cc create mode 100644 tests/base/work_stream_01a.output create mode 100644 tests/base/work_stream_01b.cc create mode 100644 tests/base/work_stream_01b.output diff --git a/doc/news/changes/minor/20190502Jean-PaulPelteret-1 b/doc/news/changes/minor/20190502Jean-PaulPelteret-1 new file mode 100644 index 0000000000..8f41a0d8aa --- /dev/null +++ b/doc/news/changes/minor/20190502Jean-PaulPelteret-1 @@ -0,0 +1,5 @@ +Improved: The Workstream::run() function is now capable of working with iterator +ranges, or any general iterable object that defines the `begin()` and `end()` +of a range of elements to iterate over. +
+(Jean-Paul Pelteret, 2019/05/02) diff --git a/include/deal.II/base/work_stream.h b/include/deal.II/base/work_stream.h index 555c35c98d..c2fa346741 100644 --- a/include/deal.II/base/work_stream.h +++ b/include/deal.II/base/work_stream.h @@ -20,6 +20,7 @@ # include # include +# include # include # include # include @@ -33,6 +34,7 @@ # endif # include +# include # include # include # include @@ -1089,6 +1091,72 @@ namespace WorkStream } + + /** + * Same as the function above, but for iterator ranges and C-style arrays. + * A class that fulfills the requirements of an iterator range defines the + * functions `IteratorRangeType::begin()` and `IteratorRangeType::end()`, + * both of which return iterators to elements that form the bounds of the + * range. + */ + template ::value>::type> + void + run(IteratorRangeType iterator_range, + Worker worker, + Copier copier, + const ScratchData &sample_scratch_data, + const CopyData & sample_copy_data, + const unsigned int queue_length = 2 * MultithreadInfo::n_threads(), + const unsigned int chunk_size = 8) + { + // Call the function above + run(iterator_range.begin(), + iterator_range.end(), + worker, + copier, + sample_scratch_data, + sample_copy_data, + queue_length, + chunk_size); + } + + + + /** + * Same as the function above, but for deal.II's IteratorRange. + */ + template + void + run(const IteratorRange &iterator_range, + Worker worker, + Copier copier, + const ScratchData & sample_scratch_data, + const CopyData & sample_copy_data, + const unsigned int queue_length = 2 * MultithreadInfo::n_threads(), + const unsigned int chunk_size = 8) + { + // Call the function above + run(iterator_range.begin(), + iterator_range.end(), + worker, + copier, + sample_scratch_data, + sample_copy_data, + queue_length, + chunk_size); + } + + // Implementation 3: template + void + run(const typename IteratorRange::IteratorOverIterators &begin, + const typename IteratorRange< + typename identity::type>::IteratorOverIterators &end, + MainClass & main_object, + void (MainClass::*worker)(const Iterator &, ScratchData &, CopyData &), + void (MainClass::*copier)(const CopyData &), + const ScratchData &sample_scratch_data, + const CopyData & sample_copy_data, + const unsigned int queue_length = 2 * MultithreadInfo::n_threads(), + const unsigned int chunk_size = 8) + { + // forward to the other function + run(begin, + end, + std::bind(worker, + std::ref(main_object), + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3), + std::bind(copier, std::ref(main_object), std::placeholders::_1), + sample_scratch_data, + sample_copy_data, + queue_length, + chunk_size); + } + + + + /** + * Same as the function above, but for iterator ranges and C-style arrays. + * A class that fulfills the requirements of an iterator range defines the + * functions `IteratorRangeType::begin()` and `IteratorRangeType::end()`, + * both of which return iterators to elements that form the bounds of the + * range. + */ + template ::value>::type> + void + run(IteratorRangeType iterator_range, + MainClass & main_object, + void (MainClass::*worker)( + const typename identity::type::iterator &, + ScratchData &, + CopyData &), + void (MainClass::*copier)(const CopyData &), + const ScratchData &sample_scratch_data, + const CopyData & sample_copy_data, + const unsigned int queue_length = 2 * MultithreadInfo::n_threads(), + const unsigned int chunk_size = 8) + { + // Call the function above + run(std::begin(iterator_range), + std::end(iterator_range), + main_object, + worker, + copier, + sample_scratch_data, + sample_copy_data, + queue_length, + chunk_size); + } + + + + /** + * Same as the function above, but for deal.II's IteratorRange. + */ + template + void + run(IteratorRange iterator_range, + MainClass & main_object, + void (MainClass::*worker)(const Iterator &, ScratchData &, CopyData &), + void (MainClass::*copier)(const CopyData &), + const ScratchData &sample_scratch_data, + const CopyData & sample_copy_data, + const unsigned int queue_length = 2 * MultithreadInfo::n_threads(), + const unsigned int chunk_size = 8) + { + // Call the function above + run(std::begin(iterator_range), + std::end(iterator_range), + main_object, + worker, + copier, + sample_scratch_data, + sample_copy_data, + queue_length, + chunk_size); + } + } // namespace WorkStream diff --git a/tests/base/work_stream_01a.cc b/tests/base/work_stream_01a.cc new file mode 100644 index 0000000000..37c6a5014e --- /dev/null +++ b/tests/base/work_stream_01a.cc @@ -0,0 +1,72 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2008 - 2017 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.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + + +// test functions in namespace WorkStream +// This test is based off base/work_stream_01.cc, but for iterator ranges + +#include + +#include "../tests.h" + + +struct ScratchData +{}; + + +struct CopyData +{ + unsigned int computed; +}; + + +struct X +{ + void + worker(const std::vector::iterator &i, + ScratchData &, + CopyData &ad) + { + ad.computed = *i * 2; + } + + void + copier(const CopyData &ad) + { + deallog << ad.computed << std::endl; + } +}; + + +void +test() +{ + std::vector v; + for (unsigned int i = 0; i < 20; ++i) + v.push_back(i); + + X x; + WorkStream::run(v, x, &X::worker, &X::copier, ScratchData(), CopyData()); +} + + + +int +main() +{ + initlog(); + + test(); +} diff --git a/tests/base/work_stream_01a.output b/tests/base/work_stream_01a.output new file mode 100644 index 0000000000..bc020eba5c --- /dev/null +++ b/tests/base/work_stream_01a.output @@ -0,0 +1,21 @@ + +DEAL::0 +DEAL::2 +DEAL::4 +DEAL::6 +DEAL::8 +DEAL::10 +DEAL::12 +DEAL::14 +DEAL::16 +DEAL::18 +DEAL::20 +DEAL::22 +DEAL::24 +DEAL::26 +DEAL::28 +DEAL::30 +DEAL::32 +DEAL::34 +DEAL::36 +DEAL::38 diff --git a/tests/base/work_stream_01b.cc b/tests/base/work_stream_01b.cc new file mode 100644 index 0000000000..20019919e8 --- /dev/null +++ b/tests/base/work_stream_01b.cc @@ -0,0 +1,82 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2008 - 2017 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.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + + +// test functions in namespace WorkStream +// This test is based off base/work_stream_01.cc, but for iterator ranges + +#include + +#include + +#include "../tests.h" + + +struct ScratchData +{}; + + +struct CopyData +{ + unsigned int computed; +}; + + +using IteratorType = typename std::vector::iterator; +using IteratorRangeType = IteratorRange; + +static_assert( + std::is_same::value, + "Iterator types not the same"); + +struct X +{ + void + worker(const IteratorType &i, ScratchData &, CopyData &ad) + { + ad.computed = *i * 2; + } + + void + copier(const CopyData &ad) + { + deallog << ad.computed << std::endl; + } +}; + + +void +test() +{ + std::vector v; + for (unsigned int i = 0; i < 20; ++i) + v.push_back(i); + + const IteratorRangeType iterator_range(v.begin(), v.end()); + + X x; + WorkStream::run( + iterator_range, x, &X::worker, &X::copier, ScratchData(), CopyData()); +} + + + +int +main() +{ + initlog(); + + test(); +} diff --git a/tests/base/work_stream_01b.output b/tests/base/work_stream_01b.output new file mode 100644 index 0000000000..bc020eba5c --- /dev/null +++ b/tests/base/work_stream_01b.output @@ -0,0 +1,21 @@ + +DEAL::0 +DEAL::2 +DEAL::4 +DEAL::6 +DEAL::8 +DEAL::10 +DEAL::12 +DEAL::14 +DEAL::16 +DEAL::18 +DEAL::20 +DEAL::22 +DEAL::24 +DEAL::26 +DEAL::28 +DEAL::30 +DEAL::32 +DEAL::34 +DEAL::36 +DEAL::38 -- 2.39.5