From 9432c81060b1da1ce828686708e496c6d59563a5 Mon Sep 17 00:00:00 2001 From: Damien L-G Date: Thu, 13 Jul 2023 23:42:01 -0400 Subject: [PATCH 1/2] Check that work is enqueued on the user-provided execution space instance --- test/CMakeLists.txt | 1 + .../tstKokkosToolsExecutionSpaceInstances.cpp | 138 ++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 test/tstKokkosToolsExecutionSpaceInstances.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6a5e426c2..aae8c8a26 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -152,6 +152,7 @@ list(APPEND ARBORX_TEST_QUERY_TREE_SOURCES tstQueryTreeTraversalPolicy.cpp tstQueryTreeIntersectsKDOP.cpp tstKokkosToolsAnnotations.cpp + tstKokkosToolsExecutionSpaceInstances.cpp utf_main.cpp ) add_executable(ArborX_Test_QueryTree.exe ${ARBORX_TEST_QUERY_TREE_SOURCES}) diff --git a/test/tstKokkosToolsExecutionSpaceInstances.cpp b/test/tstKokkosToolsExecutionSpaceInstances.cpp new file mode 100644 index 000000000..986e2d3e9 --- /dev/null +++ b/test/tstKokkosToolsExecutionSpaceInstances.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** + * Copyright (c) 2017-2023 by the ArborX authors * + * All rights reserved. * + * * + * This file is part of the ArborX library. ArborX is * + * distributed under a BSD 3-clause license. For the licensing terms see * + * the LICENSE file in the top-level directory. * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ****************************************************************************/ + +#include "ArborX_EnableDeviceTypes.hpp" // ARBORX_DEVICE_TYPES +#include + +#include + +#include + +#include "Search_UnitTestHelpers.hpp" + +BOOST_AUTO_TEST_SUITE(KokkosToolsExecutionSpaceInstances) + +namespace tt = boost::test_tools; + +namespace +{ +// Lambdas can only be converted to function pointers if they do not capture. +// Using a global non-static variable in an unnamed namespace to "capture" the +// device id. +uint32_t arborx_test_device_id = -1; +uint32_t arborx_test_root_device_id = -1; + +void arborx_test_parallel_x_callback(char const *label, uint32_t device_id, + uint64_t * /*kernel_id*/) +{ + std::string label_str(label); + + for (std::string s : {"Kokkos::View::destruction []"}) + if (label_str.find(s) != std::string::npos) + return; + + BOOST_TEST(device_id == arborx_test_device_id, + "\"" << label + << "\" kernel not on the right execution space instance: " + << device_id << " != " << arborx_test_device_id); +} + +template +void arborx_test_set_tools_callbacks(ExecutionSpace exec) +{ + arborx_test_device_id = Kokkos::Tools::Experimental::device_id(exec); + arborx_test_root_device_id = + Kokkos::Tools::Experimental::device_id_root(); + + Kokkos::Tools::Experimental::set_begin_parallel_for_callback( + arborx_test_parallel_x_callback); + Kokkos::Tools::Experimental::set_begin_parallel_reduce_callback( + arborx_test_parallel_x_callback); + Kokkos::Tools::Experimental::set_begin_parallel_scan_callback( + arborx_test_parallel_x_callback); +} + +void arborx_test_unset_tools_callbacks() +{ + Kokkos::Tools::Experimental::set_begin_parallel_for_callback(nullptr); + Kokkos::Tools::Experimental::set_begin_parallel_reduce_callback(nullptr); + Kokkos::Tools::Experimental::set_begin_parallel_scan_callback(nullptr); + arborx_test_device_id = -1; + arborx_test_root_device_id = -1; +} + +} // namespace + +BOOST_AUTO_TEST_CASE_TEMPLATE(bvh_bvh_execution_space_instance, DeviceType, + ARBORX_DEVICE_TYPES) +{ + using Tree = ArborX::BVH; + using ExecutionSpace = typename DeviceType::execution_space; + + auto exec = Kokkos::Experimental::partition_space(ExecutionSpace{}, 1)[0]; + arborx_test_set_tools_callbacks(exec); + + { // default constructed + Tree tree; + } + + { // empty + auto tree = make(exec, {}); + } + + { // one leaf + auto tree = make(exec, { + {{{0, 0, 0}}, {{1, 1, 1}}}, + }); + } + + { // two leaves + auto tree = make(exec, { + {{{0, 0, 0}}, {{1, 1, 1}}}, + {{{0, 0, 0}}, {{1, 1, 1}}}, + }); + } + + arborx_test_unset_tools_callbacks(); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(bvh_query_execution_space_instance, DeviceType, + ARBORX_DEVICE_TYPES) +{ + using ExecutionSpace = typename DeviceType::execution_space; + + auto tree = make>( + ExecutionSpace{}, { + {{{0, 0, 0}}, {{1, 1, 1}}}, + {{{0, 0, 0}}, {{1, 1, 1}}}, + }); + + auto exec = Kokkos::Experimental::partition_space(ExecutionSpace{}, 1)[0]; + arborx_test_set_tools_callbacks(exec); + + // spatial predicates + query(exec, tree, + makeIntersectsBoxQueries({ + {{{0, 0, 0}}, {{1, 1, 1}}}, + {{{0, 0, 0}}, {{1, 1, 1}}}, + })); + + // nearest predicates + query(exec, tree, + makeNearestQueries({ + {{{0, 0, 0}}, 1}, + {{{0, 0, 0}}, 2}, + })); + + arborx_test_unset_tools_callbacks(); +} + +BOOST_AUTO_TEST_SUITE_END() From 7c28f20436aff4c09bde0618d86a81a1ab76e9c7 Mon Sep 17 00:00:00 2001 From: Andrey Prokopenko Date: Fri, 21 Jun 2024 17:28:39 -0400 Subject: [PATCH 2/2] Switch query creation to use execution space --- test/Search_UnitTestHelpers.hpp | 90 ++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/test/Search_UnitTestHelpers.hpp b/test/Search_UnitTestHelpers.hpp index ffee07ef5..75e4bc479 100644 --- a/test/Search_UnitTestHelpers.hpp +++ b/test/Search_UnitTestHelpers.hpp @@ -146,91 +146,114 @@ makeDistributedTree(MPI_Comm comm, std::vector const &b) #endif template -auto makeIntersectsBoxQueries(std::vector const &boxes) +auto makeIntersectsBoxQueries( + std::vector const &boxes, + typename DeviceType::execution_space const &exec_space = {}) { int const n = boxes.size(); Kokkos::View - queries("Testing::intersecting_with_box_predicates", n); - auto queries_host = Kokkos::create_mirror_view(queries); + queries(Kokkos::view_alloc(Kokkos::WithoutInitializing, + "Testing::intersecting_with_box_predicates"), + n); + auto queries_host = + Kokkos::create_mirror_view(Kokkos::WithoutInitializing, queries); for (int i = 0; i < n; ++i) queries_host(i) = ArborX::intersects(boxes[i]); - Kokkos::deep_copy(queries, queries_host); + Kokkos::deep_copy(exec_space, queries, queries_host); return queries; } template auto makeIntersectsBoxWithAttachmentQueries( - std::vector const &boxes, std::vector const &data) + std::vector const &boxes, std::vector const &data, + typename DeviceType::execution_space const &exec_space = {}) { int const n = boxes.size(); Kokkos::View - queries("Testing::intersecting_with_box_with_attachment_predicates", n); - auto queries_host = Kokkos::create_mirror_view(queries); + queries(Kokkos::view_alloc( + Kokkos::WithoutInitializing, + "Testing::intersecting_with_box_with_attachment_predicates"), + n); + auto queries_host = + Kokkos::create_mirror_view(Kokkos::WithoutInitializing, queries); for (int i = 0; i < n; ++i) queries_host(i) = ArborX::attach(ArborX::intersects(boxes[i]), data[i]); - Kokkos::deep_copy(queries, queries_host); + Kokkos::deep_copy(exec_space, queries, queries_host); return queries; } template auto makeNearestQueries( - std::vector> const &points) + std::vector> const &points, + typename DeviceType::execution_space const &exec_space = {}) { // NOTE: `points` is not a very descriptive name here. It stores both the // actual point and the number k of neighbors to query for. int const n = points.size(); Kokkos::View *, DeviceType> queries( - "Testing::nearest_queries", n); - auto queries_host = Kokkos::create_mirror_view(queries); + Kokkos::view_alloc(Kokkos::WithoutInitializing, + "Testing::nearest_queries"), + n); + auto queries_host = + Kokkos::create_mirror_view(Kokkos::WithoutInitializing, queries); for (int i = 0; i < n; ++i) queries_host(i) = ArborX::nearest(points[i].first, points[i].second); - Kokkos::deep_copy(queries, queries_host); + Kokkos::deep_copy(exec_space, queries, queries_host); return queries; } template auto makeBoxNearestQueries( - std::vector> const &boxes) + std::vector> const &boxes, + typename DeviceType::execution_space const &exec_space = {}) { // NOTE: `boxes` is not a very descriptive name here. It stores both the // corners of the boxe and the number k of neighbors to query for. int const n = boxes.size(); Kokkos::View *, DeviceType> queries( - "Testing::nearest_queries", n); - auto queries_host = Kokkos::create_mirror_view(queries); + Kokkos::view_alloc(Kokkos::WithoutInitializing, + "Testing::nearest_queries"), + n); + auto queries_host = + Kokkos::create_mirror_view(Kokkos::WithoutInitializing, queries); for (int i = 0; i < n; ++i) queries_host(i) = ArborX::nearest( ArborX::Box{std::get<0>(boxes[i]), std::get<1>(boxes[i])}, std::get<2>(boxes[i])); - Kokkos::deep_copy(queries, queries_host); + Kokkos::deep_copy(exec_space, queries, queries_host); return queries; } template auto makeSphereNearestQueries( - std::vector> const &spheres) + std::vector> const &spheres, + typename DeviceType::execution_space const &exec_space = {}) { // NOTE: `sphere` is not a very descriptive name here. It stores both the // center and the radius of the sphere and the number k of neighbors to query // for. int const n = spheres.size(); Kokkos::View *, DeviceType> queries( - "Testing::nearest_queries", n); - auto queries_host = Kokkos::create_mirror_view(queries); + Kokkos::view_alloc(Kokkos::WithoutInitializing, + "Testing::nearest_queries"), + n); + auto queries_host = + Kokkos::create_mirror_view(Kokkos::WithoutInitializing, queries); for (int i = 0; i < n; ++i) queries_host(i) = ArborX::nearest( ArborX::Sphere{std::get<0>(spheres[i]), std::get<1>(spheres[i])}, std::get<2>(spheres[i])); - Kokkos::deep_copy(queries, queries_host); + Kokkos::deep_copy(exec_space, queries, queries_host); return queries; } template auto makeNearestWithAttachmentQueries( std::vector> const &points, - std::vector const &data) + std::vector const &data, + typename DeviceType::execution_space const &exec_space = {}) { // NOTE: `points` is not a very descriptive name here. It stores both the // actual point and the number k of neighbors to query for. @@ -238,30 +261,37 @@ auto makeNearestWithAttachmentQueries( Kokkos::View{}, Data{})) *, DeviceType> - queries("Testing::nearest_queries", n); - auto queries_host = Kokkos::create_mirror_view(queries); + queries(Kokkos::view_alloc(Kokkos::WithoutInitializing, + "Testing::nearest_queries"), + n); + auto queries_host = + Kokkos::create_mirror_view(Kokkos::WithoutInitializing, queries); for (int i = 0; i < n; ++i) queries_host(i) = ArborX::attach( ArborX::nearest(points[i].first, points[i].second), data[i]); - Kokkos::deep_copy(queries, queries_host); + Kokkos::deep_copy(exec_space, queries, queries_host); return queries; } template -Kokkos::View -makeIntersectsSphereQueries( - std::vector> const &points) +auto makeIntersectsSphereQueries( + std::vector> const &points, + typename DeviceType::execution_space const &exec_space = {}) { // NOTE: `points` is not a very descriptive name here. It stores both the // actual point and the radius for the search around that point. int const n = points.size(); Kokkos::View - queries("Testing::intersecting_with_sphere_predicates", n); - auto queries_host = Kokkos::create_mirror_view(queries); + queries( + Kokkos::view_alloc(Kokkos::WithoutInitializing, + "Testing::intersecting_with_sphere_predicates"), + n); + auto queries_host = + Kokkos::create_mirror_view(Kokkos::WithoutInitializing, queries); for (int i = 0; i < n; ++i) queries_host(i) = ArborX::intersects(ArborX::Sphere{points[i].first, points[i].second}); - Kokkos::deep_copy(queries, queries_host); + Kokkos::deep_copy(exec_space, queries, queries_host); return queries; }