From 4276ffe6f0f1f28217eb6f8f064f5b86d7b89862 Mon Sep 17 00:00:00 2001 From: Tobias Leibner <tobias.leibner@googlemail.com> Date: Wed, 31 Oct 2018 10:48:23 +0100 Subject: [PATCH] [walker] make usable with new PerThreadValue --- .gitsuper | 8 +- dune/xt/grid/test/walker.cc | 26 +++-- dune/xt/grid/walker.hh | 187 +++++++++++++++++++++--------------- 3 files changed, 132 insertions(+), 89 deletions(-) diff --git a/.gitsuper b/.gitsuper index e65b22659..60ad864fd 100644 --- a/.gitsuper +++ b/.gitsuper @@ -14,10 +14,10 @@ status = 1a3bcab04b011a5d6e44f9983cae6ff89fa695e8 bin (heads/master) 741e4f8e53bdd3e1b6e19d84eb22b6e3dc48526c dune-python (remotes/origin/releases/2.5) 26cc8cb4161a3a51002ab2a81b8c81d2c951ee79 dune-testtools (remotes/origin/p/renemilk/testname_listing_hack_no-skiptest) 0a74e7dd0b2115778a5d490dab08a2ed07fcaa1e dune-uggrid (v2.5.2) - +effefc7695eba0c0ca94fff0f93026b86501027e dune-xt-common (heads/master) + +7d4cb994b3aad0e0ff73172b187e35bbf191bf29 dune-xt-common (heads/dailywork_tleibner) +3e3f3bf06e21cbbf3c0a559891b44c6f5d987d0f dune-xt-data (heads/master) +f05aa7470ead4150ca7a91894cd2ad77dfcedc46 dune-xt-functions (heads/new-master) - +be11e17850621da0847812f667c650cd008ae281 dune-xt-grid (heads/new-master) + +5be0c7c0e69d6364022421b866016d6443280cf2 dune-xt-grid (heads/new-master) +f6904b69f9a3ee5d45ee824d3b244e59cfed7ff4 dune-xt-la (heads/master) 09d0378f616b94d68bcdd9fc6114813181849ec0 scripts (heads/master) commit = 5f5841ee7a2dff290b98845c46262151752189c1 @@ -95,7 +95,7 @@ commit = 0a74e7dd0b2115778a5d490dab08a2ed07fcaa1e [submodule.dune-xt-common] remote = git@github.com:dune-community/dune-xt-common.git status = 2424627f0ad5de7e4aaa5e7f48bc2a02414d95a1 .vcsetup (heads/master) -commit = effefc7695eba0c0ca94fff0f93026b86501027e +commit = 7d4cb994b3aad0e0ff73172b187e35bbf191bf29 [submodule.dune-xt-data] remote = git@github.com:dune-community/dune-xt-data @@ -110,7 +110,7 @@ commit = f05aa7470ead4150ca7a91894cd2ad77dfcedc46 [submodule.dune-xt-grid] remote = git@github.com:dune-community/dune-xt-grid.git status = 2424627f0ad5de7e4aaa5e7f48bc2a02414d95a1 .vcsetup (heads/master) -commit = be11e17850621da0847812f667c650cd008ae281 +commit = 5be0c7c0e69d6364022421b866016d6443280cf2 [submodule.dune-xt-la] remote = git@github.com:dune-community/dune-xt-la.git diff --git a/dune/xt/grid/test/walker.cc b/dune/xt/grid/test/walker.cc index cbf6f4524..e30a80c1d 100644 --- a/dune/xt/grid/test/walker.cc +++ b/dune/xt/grid/test/walker.cc @@ -48,7 +48,7 @@ struct GridWalkerTest : public ::testing::Test { const auto gv = grid_prv.grid().leafGridView(); Walker<GridLayerType> walker(gv); - const auto correct_size = gv.size(0); + const auto num_elements = gv.size(0); atomic<size_t> count(0); atomic<size_t> intersection_count(0); auto counter = GenericElementFunctor<GridLayerType>([] {}, [&count](const EntityType&) { count++; }, [] {}); @@ -66,7 +66,8 @@ struct GridWalkerTest : public ::testing::Test auto test4 = [&] { walker.append(intersection_counter).walk(false); }; auto test5 = [&] { walker.append(intersection_counter).walk(true); }; - list<function<void()>> tests({test1, test2, test3, test4, test5}); + list<function<void()>> element_tests({test1, test2, test3}); + list<function<void()>> intersection_tests({test4, test5}); #if DUNE_VERSION_NEWER(DUNE_COMMON, 3, 9) && HAVE_TBB // EXADUNE // exadune guard for SeedListPartitioning auto test0 = [&] { @@ -80,10 +81,16 @@ struct GridWalkerTest : public ::testing::Test tests.push_back(test0); #endif // DUNE_VERSION_NEWER(DUNE_COMMON, 3, 9) && HAVE_TBB - for (const auto& test : tests) { + for (const auto& test : element_tests) { count = 0; test(); - EXPECT_EQ(count, correct_size); + EXPECT_EQ(num_elements, count); + } + const auto faces_per_element = 2 * griddim; // only for cube grids + for (const auto& test : intersection_tests) { + intersection_count = 0; + test(); + EXPECT_EQ(num_elements * faces_per_element, intersection_count); } } @@ -113,9 +120,10 @@ struct GridWalkerTest : public ::testing::Test Walker<GridLayerType> walker(gv); size_t filter_count = 0, all_count = 0, inner_count = 0, inner_set_count = 0; - auto filter_counter = GenericElementFunctor<GridLayerType>([] {}, [&](...) { filter_count++; }, [] {}); - auto inner_filter_counter = GenericElementFunctor<GridLayerType>([] {}, [&](...) { inner_set_count++; }, [] {}); - auto all_counter = GenericElementFunctor<GridLayerType>([] {}, [&](...) { all_count++; }, [] {}); + auto filter_counter = GenericElementFunctor<GridLayerType>([] {}, [&](const auto&) { filter_count++; }, [] {}); + auto inner_filter_counter = + GenericElementFunctor<GridLayerType>([] {}, [&](const auto&) { inner_set_count++; }, [] {}); + auto all_counter = GenericElementFunctor<GridLayerType>([] {}, [&](const auto&) { all_count++; }, [] {}); auto inner_counter = GenericElementFunctor<GridLayerType>( [] {}, [&](const auto& e) { inner_count += e.partitionType() == Dune::PartitionType::InteriorEntity; }, [] {}); @@ -137,8 +145,8 @@ struct GridWalkerTest : public ::testing::Test Walker<GridLayerType> walker(gv); size_t all_count = 0, inner_count = 0; - auto all_set_counter = GenericElementFunctor<GridLayerType>([] {}, [&](...) { all_count++; }, [] {}); - auto inner_set_counter = GenericElementFunctor<GridLayerType>([] {}, [&](...) { inner_count++; }, [] {}); + auto all_set_counter = GenericElementFunctor<GridLayerType>([] {}, [&](const auto&) { all_count++; }, [] {}); + auto inner_set_counter = GenericElementFunctor<GridLayerType>([] {}, [&](const auto&) { inner_count++; }, [] {}); ApplyOn::PartitionSetElements<GridLayerType, Dune::Partitions::Interior> on_interior_partitionset{}; ApplyOn::PartitionSetElements<GridLayerType, Dune::Partitions::All> on_all_partitionset{}; walker.append(inner_set_counter, on_interior_partitionset); diff --git a/dune/xt/grid/walker.hh b/dune/xt/grid/walker.hh index e09f4ac44..667cbc9b3 100644 --- a/dune/xt/grid/walker.hh +++ b/dune/xt/grid/walker.hh @@ -79,6 +79,12 @@ public: { } + ElementFunctorWrapper(const ThisType& other) + : functor_(other.functor_->copy()) + , filter_(other.filter_->copy()) + { + } + const FilterType& filter() const { return *filter_; @@ -116,6 +122,12 @@ public: { } + IntersectionFunctorWrapper(const ThisType& other) + : functor_(other.functor_->copy()) + , filter_(other.filter_->copy()) + { + } + const FilterType& filter() const { return *filter_; @@ -157,6 +169,13 @@ public: { } + ElementAndIntersectionFunctorWrapper(const ThisType& other) + : functor_(other.functor_->copy()) + , element_filter_(other.element_filter_->copy()) + , intersection_filter_(other.intersection_filter_->copy()) + { + } + const ElementFilterType& element_filter() const { return *element_filter_; @@ -202,11 +221,12 @@ private: using VoidFunctionType = std::function<void()>; template <typename WrapperType, class... Args> - void emplace_all(Common::PerThreadValue<std::list<std::shared_ptr<WrapperType>>>& thread_storage, Args&&... args) + void emplace_all(std::list<WrapperType>& storage, + Common::PerThreadValue<std::list<WrapperType>>& thread_storage, + Args&&... args) { - for (auto&& local_list : thread_storage) { - local_list.emplace_back(new WrapperType(std::forward<Args>(args)...)); - } + storage.emplace_back(std::forward<Args>(args)...); + thread_storage = Common::PerThreadValue<std::list<WrapperType>>(storage); } public: @@ -216,36 +236,20 @@ public: } Walker(const ThisType& other) - : BaseType() - , grid_view_(other.grid_view_) - { - // Since all Common::PerThreadValue are created with the same size given by the global singleton threadManager(), - // we just assume they are of the same size! - // Copy the element functors ... - auto zip_emplace = [](auto& target_thread_ctr, const auto& source_thread_ctr, auto& gen_function) { - auto target_wrappers_it = target_thread_ctr.begin(); - auto source_wrappers_it = source_thread_ctr.begin(); - for (; target_wrappers_it != target_thread_ctr.end() && source_wrappers_it != source_thread_ctr.end(); - ++target_wrappers_it, ++source_wrappers_it) { - auto& target__wrappers = *target_wrappers_it; - for (auto&& source_wrapper : *source_wrappers_it) { - target__wrappers.emplace_back(gen_function(*source_wrapper)); - } - } - }; - auto el_wrapper = [](auto&& wrapper) { - return new typename std::decay<decltype(wrapper)>::type(wrapper.functor(), wrapper.filter()); - }; - zip_emplace(element_functor_wrappers_, other.element_functor_wrappers_, el_wrapper); - zip_emplace(intersection_functor_wrappers_, other.intersection_functor_wrappers_, el_wrapper); - - auto elint_wrapper = [](auto&& wrapper) { - return new typename std::decay<decltype(wrapper)>::type( - wrapper.functor(), wrapper.element_filter(), wrapper.intersection_filter()); - }; - zip_emplace( - element_and_intersection_functor_wrappers_, other.element_and_intersection_functor_wrappers_, elint_wrapper); - } // Walker(...) + : grid_view_(other.grid_view_) + , stored_element_functor_wrappers_(other.stored_element_functor_wrappers_) + , stored_intersection_functor_wrappers_(other.stored_intersection_functor_wrappers_) + , stored_element_and_intersection_functor_wrappers_(other.stored_element_and_intersection_functor_wrappers_) + { + element_functor_wrappers_ = Common::PerThreadValue<std::list<internal::ElementFunctorWrapper<GridViewType>>>( + stored_element_functor_wrappers_); + intersection_functor_wrappers_ = + Common::PerThreadValue<std::list<internal::IntersectionFunctorWrapper<GridViewType>>>( + stored_intersection_functor_wrappers_); + element_and_intersection_functor_wrappers_ = + Common::PerThreadValue<std::list<internal::ElementAndIntersectionFunctorWrapper<GridViewType>>>( + stored_element_and_intersection_functor_wrappers_); + } Walker(ThisType&& source) = default; @@ -268,26 +272,32 @@ public: ThisType& append(ElementFunctor<GV>& functor, const ElementFilter<GV>& filter = ApplyOn::AllElements<GV>()) { - emplace_all(element_functor_wrappers_, functor, filter); + emplace_all(stored_element_functor_wrappers_, element_functor_wrappers_, functor, filter); return *this; } ThisType& append(ElementFunctor<GV>*&& functor, const ElementFilter<GV>& filter = ApplyOn::AllElements<GV>()) { - emplace_all(element_functor_wrappers_, *functor, filter); + emplace_all(stored_element_functor_wrappers_, element_functor_wrappers_, *functor, filter); delete functor; return *this; } ThisType& append(ElementFunctor<GV>& functor, GenericElementFilterFunctionType filter) { - emplace_all(element_functor_wrappers_, functor, ApplyOn::GenericFilteredElements<GV>(filter)); + emplace_all(stored_element_functor_wrappers_, + element_functor_wrappers_, + functor, + ApplyOn::GenericFilteredElements<GV>(filter)); return *this; } ThisType& append(ElementFunctor<GV>*&& functor, GenericElementFilterFunctionType filter) { - emplace_all(element_functor_wrappers_, *functor, ApplyOn::GenericFilteredElements<GV>(filter)); + emplace_all(stored_element_functor_wrappers_, + element_functor_wrappers_, + *functor, + ApplyOn::GenericFilteredElements<GV>(filter)); delete functor; return *this; } @@ -324,27 +334,33 @@ public: ThisType& append(IntersectionFunctor<GV>& functor, const IntersectionFilter<GV>& filter = ApplyOn::AllIntersections<GV>()) { - emplace_all(intersection_functor_wrappers_, functor, filter); + emplace_all(stored_intersection_functor_wrappers_, intersection_functor_wrappers_, functor, filter); return *this; } ThisType& append(IntersectionFunctor<GV>*&& functor, const IntersectionFilter<GV>& filter = ApplyOn::AllIntersections<GV>()) { - emplace_all(intersection_functor_wrappers_, *functor, filter); + emplace_all(stored_intersection_functor_wrappers_, intersection_functor_wrappers_, *functor, filter); delete functor; return *this; } ThisType& append(IntersectionFunctor<GV>& functor, GenericIntersectionFilterFunctionType filter) { - emplace_all(intersection_functor_wrappers_, functor, ApplyOn::GenericFilteredIntersections<GV>(filter)); + emplace_all(stored_intersection_functor_wrappers_, + intersection_functor_wrappers_, + functor, + ApplyOn::GenericFilteredIntersections<GV>(filter)); return *this; } ThisType& append(IntersectionFunctor<GV>*&& functor, GenericIntersectionFilterFunctionType filter) { - emplace_all(intersection_functor_wrappers_, *functor, ApplyOn::GenericFilteredIntersections<GV>(filter)); + emplace_all(stored_intersection_functor_wrappers_, + intersection_functor_wrappers_, + *functor, + ApplyOn::GenericFilteredIntersections<GV>(filter)); delete functor; return *this; } @@ -384,7 +400,11 @@ public: { if (&functor == this) DUNE_THROW(Common::Exceptions::you_are_using_this_wrong, "Do not append a Walker to itself!"); - emplace_all(element_and_intersection_functor_wrappers_, functor, element_filter, intersection_filter); + emplace_all(stored_element_and_intersection_functor_wrappers_, + element_and_intersection_functor_wrappers_, + functor, + element_filter, + intersection_filter); return *this; } @@ -394,7 +414,11 @@ public: { if (functor == this) DUNE_THROW(Common::Exceptions::you_are_using_this_wrong, "Do not append a Walker to itself!"); - emplace_all(element_and_intersection_functor_wrappers_, *functor, element_filter, intersection_filter); + emplace_all(stored_element_and_intersection_functor_wrappers_, + element_and_intersection_functor_wrappers_, + *functor, + element_filter, + intersection_filter); delete functor; return *this; } @@ -405,7 +429,8 @@ public: { if (&functor == this) DUNE_THROW(Common::Exceptions::you_are_using_this_wrong, "Do not append a Walker to itself!"); - emplace_all(element_and_intersection_functor_wrappers_, + emplace_all(stored_element_and_intersection_functor_wrappers_, + element_and_intersection_functor_wrappers_, functor, ApplyOn::GenericFilteredElements<GV>(element_filter), ApplyOn::GenericFilteredIntersections<GV>(intersection_filter)); @@ -418,7 +443,8 @@ public: { if (functor == this) DUNE_THROW(Common::Exceptions::you_are_using_this_wrong, "Do not append a Walker to itself!"); - emplace_all(element_and_intersection_functor_wrappers_, + emplace_all(stored_element_and_intersection_functor_wrappers_, + element_and_intersection_functor_wrappers_, *functor, ApplyOn::GenericFilteredElements<GV>(element_filter), ApplyOn::GenericFilteredIntersections<GV>(intersection_filter)); @@ -466,10 +492,10 @@ public: virtual void prepare() override { - auto prep = [](auto& pt) { - for (auto&& list : pt) { - for (auto&& wrapper : list) - wrapper->functor().prepare(); + auto prep = [](auto& functor_list) { + for (auto&& pt_wrapper : functor_list) { + for (auto&& wrapper : pt_wrapper) + wrapper.functor().prepare(); } }; prep(element_functor_wrappers_); @@ -480,12 +506,12 @@ public: virtual void apply_local(const ElementType& element) override { for (auto&& wrapper : *element_functor_wrappers_) { - if (wrapper->filter().contains(grid_view_, element)) - wrapper->functor().apply_local(element); + if (wrapper.filter().contains(grid_view_, element)) + wrapper.functor().apply_local(element); } for (auto&& wrapper : *element_and_intersection_functor_wrappers_) { - if (wrapper->element_filter().contains(grid_view_, element)) - wrapper->functor().apply_local(element); + if (wrapper.element_filter().contains(grid_view_, element)) + wrapper.functor().apply_local(element); } } // ... apply_local(...) @@ -494,21 +520,21 @@ public: const ElementType& outside_element) override { for (auto&& wrapper : *intersection_functor_wrappers_) { - if (wrapper->filter().contains(grid_view_, intersection)) - wrapper->functor().apply_local(intersection, inside_element, outside_element); + if (wrapper.filter().contains(grid_view_, intersection)) + wrapper.functor().apply_local(intersection, inside_element, outside_element); } for (auto&& wrapper : *element_and_intersection_functor_wrappers_) { - if (wrapper->intersection_filter().contains(grid_view_, intersection)) - wrapper->functor().apply_local(intersection, inside_element, outside_element); + if (wrapper.intersection_filter().contains(grid_view_, intersection)) + wrapper.functor().apply_local(intersection, inside_element, outside_element); } } // ... apply_local(...) virtual void finalize() override { - auto fin = [](auto& pt) { - for (auto&& list : pt) { - for (auto&& wrapper : list) - wrapper->functor().finalize(); + auto fin = [](auto& list) { + for (auto&& pt : list) { + for (auto&& wrapper : pt) + wrapper.functor().finalize(); } }; fin(element_and_intersection_functor_wrappers_); @@ -552,14 +578,17 @@ public: void clear() { - auto clr = [](auto& pt) { - for (auto&& list : pt) { - list.clear(); - } - }; - clr(element_functor_wrappers_); - clr(intersection_functor_wrappers_); - clr(element_and_intersection_functor_wrappers_); + stored_element_functor_wrappers_.clear(); + stored_intersection_functor_wrappers_.clear(); + stored_element_and_intersection_functor_wrappers_.clear(); + element_functor_wrappers_ = Common::PerThreadValue<std::list<internal::ElementFunctorWrapper<GridViewType>>>( + stored_element_functor_wrappers_); + intersection_functor_wrappers_ = + Common::PerThreadValue<std::list<internal::IntersectionFunctorWrapper<GridViewType>>>( + stored_intersection_functor_wrappers_); + element_and_intersection_functor_wrappers_ = + Common::PerThreadValue<std::list<internal::ElementAndIntersectionFunctorWrapper<GridViewType>>>( + stored_element_and_intersection_functor_wrappers_); } BaseType* copy() override @@ -679,15 +708,21 @@ private: } // ... walk_range(...) GridViewType grid_view_; - Common::PerThreadValue<std::list<std::shared_ptr<internal::ElementFunctorWrapper<GridViewType>>>> - element_functor_wrappers_; - Common::PerThreadValue<std::list<std::shared_ptr<internal::IntersectionFunctorWrapper<GridViewType>>>> - intersection_functor_wrappers_; - Common::PerThreadValue<std::list<std::shared_ptr<internal::ElementAndIntersectionFunctorWrapper<GridViewType>>>> + // We want each thread to have its own copy of each functor. However, as we do not know in advance how many different + // threads we will have (even if DXTC_CONFIG["threading.max_count"] is set, there may be only max_threads at a time, + // but we cannot guarantee that there will only be max_threads over the whole runtime of our program), we store the + // wrappers in a list that is shared by all threads and copy that list to the thread once a new thread tries to access + // the functors. + std::list<internal::ElementFunctorWrapper<GridViewType>> stored_element_functor_wrappers_; + std::list<internal::IntersectionFunctorWrapper<GridViewType>> stored_intersection_functor_wrappers_; + std::list<internal::ElementAndIntersectionFunctorWrapper<GridViewType>> + stored_element_and_intersection_functor_wrappers_; + Common::PerThreadValue<std::list<internal::ElementFunctorWrapper<GridViewType>>> element_functor_wrappers_; + Common::PerThreadValue<std::list<internal::IntersectionFunctorWrapper<GridViewType>>> intersection_functor_wrappers_; + Common::PerThreadValue<std::list<internal::ElementAndIntersectionFunctorWrapper<GridViewType>>> element_and_intersection_functor_wrappers_; }; // class Walker - template <class GV> Walker<GV> make_walker(GV grid_view) { -- GitLab