Skip to content

Commit

Permalink
Detector Move (Assignment), main branch (2024.03.18.) (#701)
Browse files Browse the repository at this point in the history
This is to allow us moving detray::detector objects around. Copying them remains forbidden, but moving such objects can come in handy in some cases.

Updated the unit tests that I thought would be most appropriate for this, to now also test moving detray::detector objects. (Changed the existing unit testing code for this a bit, to be able to re-use the existing "content checks" using lambdas.)
  • Loading branch information
krasznaa authored Mar 18, 2024
1 parent 86a36f4 commit c926d73
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 107 deletions.
7 changes: 6 additions & 1 deletion core/include/detray/core/detail/multi_store.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** Detray library, part of the ACTS project (R&D line)
*
* (c) 2022-2023 CERN for the benefit of the ACTS project
* (c) 2022-2024 CERN for the benefit of the ACTS project
*
* Mozilla Public License Version 2.0
*/
Expand Down Expand Up @@ -70,6 +70,8 @@ class multi_store {

/// Empty container
constexpr multi_store() = default;
/// Move constructor
constexpr multi_store(multi_store &&) = default;

// Delegate constructors to tuple container, which handles the memory

Expand Down Expand Up @@ -101,6 +103,9 @@ class multi_store {
DETRAY_HOST_DEVICE multi_store(tuple_view_t &view)
: m_tuple_container(view) {}

/// Move assignment operator
multi_store &operator=(multi_store &&) = default;

/// @returns a pointer to the underlying tuple container - const
DETRAY_HOST_DEVICE
constexpr auto data() const noexcept -> const tuple_type * {
Expand Down
6 changes: 5 additions & 1 deletion core/include/detray/core/detail/tuple_container.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** Detray library, part of the ACTS project (R&D line)
*
* (c) 2022-2023 CERN for the benefit of the ACTS project
* (c) 2022-2024 CERN for the benefit of the ACTS project
*
* Mozilla Public License Version 2.0
*/
Expand Down Expand Up @@ -43,6 +43,10 @@ class tuple_container {

/// Empty container - default alloc
constexpr tuple_container() = default;
/// Move constructor
constexpr tuple_container(tuple_container &&) = default;
/// Move assignment operator
constexpr tuple_container &operator=(tuple_container &&) = default;

/// Copy construct from element types
constexpr explicit tuple_container(const Ts &... args) : _tuple(args...) {}
Expand Down
10 changes: 8 additions & 2 deletions core/include/detray/core/detector.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** Detray library, part of the ACTS project (R&D line)
*
* (c) 2021-2023 CERN for the benefit of the ACTS project
* (c) 2021-2024 CERN for the benefit of the ACTS project
*
* Mozilla Public License Version 2.0
*/
Expand Down Expand Up @@ -161,10 +161,16 @@ class detector {
// The detector holds a lot of data and should never be copied
detector(const detector &) = delete;
detector &operator=(const detector &) = delete;
detector(detector &&) = default;

/// Allowed constructors
/// @{

/// Move constructor
detector(detector &&) = default;

/// Move assignment
detector &operator=(detector &&) = default;

/// Default construction
/// @param resource memory resource for the allocation of members
DETRAY_HOST
Expand Down
21 changes: 21 additions & 0 deletions core/include/detray/utils/grid/detail/bin_storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ class bin_storage : public detray::ranges::view_interface<

/// Default constructor
bin_storage() = default;
/// Copy constructor
bin_storage(const bin_storage&) = default;
/// Move constructor
bin_storage(bin_storage&&) = default;

/// Copy assignment
bin_storage& operator=(const bin_storage&) = default;
/// Move assignment
bin_storage& operator=(bin_storage&&) = default;

/// Construct containers using a memory resources
template <bool owner = is_owning, std::enable_if_t<owner, bool> = true>
Expand Down Expand Up @@ -138,6 +147,9 @@ struct dynamic_bin_container {
dynamic_bin_container(const dynamic_bin_container& other) = default;
dynamic_bin_container(dynamic_bin_container&& other) = default;

dynamic_bin_container& operator=(const dynamic_bin_container&) = default;
dynamic_bin_container& operator=(dynamic_bin_container&&) = default;

/// Device-side construction from a vecmem based view type
template <typename view_t,
typename std::enable_if_t<detail::is_device_view_v<view_t>,
Expand Down Expand Up @@ -311,6 +323,10 @@ class bin_storage<is_owning, detray::bins::dynamic_array<entry_t>, containers>

/// Default constructor
bin_storage() = default;
/// Copy constructor
bin_storage(const bin_storage&) = default;
/// Move constructor
bin_storage(bin_storage&&) = default;

/// Construct containers using a memory resources
template <bool owner = is_owning, std::enable_if_t<owner, bool> = true>
Expand Down Expand Up @@ -341,6 +357,11 @@ class bin_storage<is_owning, detray::bins::dynamic_array<entry_t>, containers>
: m_bin_data(detray::detail::get<0>(view.m_view)),
m_entry_data(detray::detail::get<1>(view.m_view)) {}

/// Copy assignment
bin_storage& operator=(const bin_storage&) = default;
/// Move assignment
bin_storage& operator=(bin_storage&&) = default;

const bin_range_t& bin_data() const { return m_bin_data; }
const entry_range_t& entry_data() const { return m_entry_data; }

Expand Down
19 changes: 19 additions & 0 deletions core/include/detray/utils/grid/grid_collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,25 @@ class grid_collection<
m_bin_edge_offsets(detail::get<2>(view.m_view)),
m_bin_edges(detail::get<3>(view.m_view)) {}

/// Move constructor
DETRAY_HOST_DEVICE grid_collection(grid_collection &&other) noexcept
: m_bin_offsets(std::move(other.m_bin_offsets)),
m_bins(std::move(other.m_bins)),
m_bin_edge_offsets(std::move(other.m_bin_edge_offsets)),
m_bin_edges(std::move(other.m_bin_edges)) {}

/// Move assignment
DETRAY_HOST_DEVICE grid_collection &operator=(
grid_collection &&other) noexcept {
if (this != &other) {
m_bin_offsets = std::move(other.m_bin_offsets);
m_bins = std::move(other.m_bins);
m_bin_edge_offsets = std::move(other.m_bin_edge_offsets);
m_bin_edges = std::move(other.m_bin_edges);
}
return *this;
}

/// @returns the number of grids in the collection - const
DETRAY_HOST_DEVICE
constexpr auto size() const noexcept -> dindex {
Expand Down
7 changes: 4 additions & 3 deletions tests/benchmarks/cuda/benchmark_propagator_cuda.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** Detray library, part of the ACTS project (R&D line)
*
* (c) 2022-2023 CERN for the benefit of the ACTS project
* (c) 2022-2024 CERN for the benefit of the ACTS project
*
* Mozilla Public License Version 2.0
*/
Expand All @@ -9,6 +9,7 @@
#include "benchmark_propagator_cuda_kernel.hpp"
#include "detray/detectors/create_toy_geometry.hpp"
#include "detray/simulation/event_generator/track_generators.hpp"
#include "detray/test/types.hpp"

// Vecmem include(s)
#include <vecmem/memory/binary_page_memory_resource.hpp>
Expand Down Expand Up @@ -47,7 +48,7 @@ static void BM_PROPAGATOR_CPU(benchmark::State &state) {

// Create the toy geometry and bfield
auto [det, names] = create_toy_geometry(host_mr, toy_cfg);
vector3 B{0.f, 0.f, 2.f * unit<scalar>::T};
test::vector3 B{0.f, 0.f, 2.f * unit<scalar>::T};
auto bfield = bfield::create_const_field(B);

// Create propagator
Expand Down Expand Up @@ -102,7 +103,7 @@ static void BM_PROPAGATOR_CUDA(benchmark::State &state) {

// Create the toy geometry
auto [det, names] = create_toy_geometry(bp_mng_mr, toy_cfg);
vector3 B{0.f, 0.f, 2.f * unit<scalar>::T};
test::vector3 B{0.f, 0.f, 2.f * unit<scalar>::T};
auto bfield = bfield::create_const_field(B);

// Get detector data
Expand Down
2 changes: 2 additions & 0 deletions tests/integration_tests/cpu/propagator/propagator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

using namespace detray;
using transform3 = test::transform3;
using point3 = test::point3;
using vector3 = test::vector3;

namespace {

Expand Down
146 changes: 90 additions & 56 deletions tests/unit_tests/cpu/core/detector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,64 +29,98 @@ GTEST_TEST(detray_core, detector) {
using finder_id = typename detector_t::accel::id;

vecmem::host_memory_resource host_mr;
detector_t d(host_mr);
detector_t d1(host_mr);
auto geo_ctx = typename detector_t::geometry_context{};

EXPECT_TRUE(d.volumes().empty());
EXPECT_TRUE(d.portals().empty());
EXPECT_TRUE(d.transform_store().empty());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_rectangle2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_portal_rectangle2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_trapezoid2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_annulus2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_cylinder2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_portal_cylinder2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_ring2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_portal_ring2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_straw_tube>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_drift_cell>());
EXPECT_TRUE(d.material_store().template empty<material_id::e_slab>());
EXPECT_TRUE(d.material_store().template empty<material_id::e_rod>());
EXPECT_TRUE(
d.accelerator_store().template empty<finder_id::e_brute_force>());
EXPECT_TRUE(d.accelerator_store().template empty<finder_id::e_disc_grid>());
EXPECT_TRUE(
d.accelerator_store().template empty<finder_id::e_cylinder2_grid>());
EXPECT_TRUE(
d.accelerator_store().template empty<finder_id::e_irr_disc_grid>());
EXPECT_TRUE(d.accelerator_store()
.template empty<finder_id::e_irr_cylinder2_grid>());
EXPECT_TRUE(d.accelerator_store().template empty<finder_id::e_default>());
// Helper lambda for checking the contents of an "empty" detector object.
auto check_empty_detector = [](auto& d) {
EXPECT_TRUE(d.volumes().empty());
EXPECT_TRUE(d.portals().empty());
EXPECT_TRUE(d.transform_store().empty());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_rectangle2>());
EXPECT_TRUE(
d.mask_store().template empty<mask_id::e_portal_rectangle2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_trapezoid2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_annulus2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_cylinder2>());
EXPECT_TRUE(
d.mask_store().template empty<mask_id::e_portal_cylinder2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_ring2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_portal_ring2>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_straw_tube>());
EXPECT_TRUE(d.mask_store().template empty<mask_id::e_drift_cell>());
EXPECT_TRUE(d.material_store().template empty<material_id::e_slab>());
EXPECT_TRUE(d.material_store().template empty<material_id::e_rod>());
EXPECT_TRUE(
d.accelerator_store().template empty<finder_id::e_brute_force>());
EXPECT_TRUE(
d.accelerator_store().template empty<finder_id::e_disc_grid>());
EXPECT_TRUE(d.accelerator_store()
.template empty<finder_id::e_cylinder2_grid>());
EXPECT_TRUE(
d.accelerator_store().template empty<finder_id::e_irr_disc_grid>());
EXPECT_TRUE(d.accelerator_store()
.template empty<finder_id::e_irr_cylinder2_grid>());
EXPECT_TRUE(
d.accelerator_store().template empty<finder_id::e_default>());
};

// Check the empty detector object.
check_empty_detector(d1);

// Add some geometrical data
prefill_detector(d, geo_ctx);
// TODO: add B-field check

EXPECT_EQ(d.volumes().size(), 1u);
EXPECT_EQ(d.portals().size(), 3u);
EXPECT_EQ(d.transform_store().size(), 3u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_rectangle2>(), 1u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_portal_rectangle2>(), 1u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_trapezoid2>(), 1u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_annulus2>(), 1u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_cylinder2>(), 0u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_portal_cylinder2>(), 0u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_ring2>(), 0u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_portal_ring2>(), 0u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_straw_tube>(), 0u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_drift_cell>(), 0u);
EXPECT_EQ(d.material_store().template size<material_id::e_slab>(), 2u);
EXPECT_EQ(d.material_store().template size<material_id::e_rod>(), 1u);
EXPECT_EQ(d.accelerator_store().template size<finder_id::e_brute_force>(),
1u);
EXPECT_EQ(d.accelerator_store().template size<finder_id::e_disc_grid>(),
0u);
EXPECT_EQ(
d.accelerator_store().template size<finder_id::e_cylinder2_grid>(), 0u);
EXPECT_EQ(d.accelerator_store().template size<finder_id::e_irr_disc_grid>(),
0u);
EXPECT_EQ(
d.accelerator_store().template size<finder_id::e_irr_cylinder2_grid>(),
0u);
EXPECT_EQ(d.accelerator_store().template size<finder_id::e_default>(), 1u);
prefill_detector(d1, geo_ctx);

// Helper lambda for checking the contents of a "filled" detector object.
auto check_filled_detector = [](auto& d) {
// TODO: add B-field check
EXPECT_EQ(d.volumes().size(), 1u);
EXPECT_EQ(d.portals().size(), 3u);
EXPECT_EQ(d.transform_store().size(), 3u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_rectangle2>(), 1u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_portal_rectangle2>(),
1u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_trapezoid2>(), 1u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_annulus2>(), 1u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_cylinder2>(), 0u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_portal_cylinder2>(),
0u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_ring2>(), 0u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_portal_ring2>(), 0u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_straw_tube>(), 0u);
EXPECT_EQ(d.mask_store().template size<mask_id::e_drift_cell>(), 0u);
EXPECT_EQ(d.material_store().template size<material_id::e_slab>(), 2u);
EXPECT_EQ(d.material_store().template size<material_id::e_rod>(), 1u);
EXPECT_EQ(
d.accelerator_store().template size<finder_id::e_brute_force>(),
1u);
EXPECT_EQ(d.accelerator_store().template size<finder_id::e_disc_grid>(),
0u);
EXPECT_EQ(
d.accelerator_store().template size<finder_id::e_cylinder2_grid>(),
0u);
EXPECT_EQ(
d.accelerator_store().template size<finder_id::e_irr_disc_grid>(),
0u);
EXPECT_EQ(d.accelerator_store()
.template size<finder_id::e_irr_cylinder2_grid>(),
0u);
EXPECT_EQ(d.accelerator_store().template size<finder_id::e_default>(),
1u);
};

// Check the filled detector object.
check_filled_detector(d1);

// Move construct a detector object.
detector_t d2{std::move(d1)};
check_filled_detector(d2);

// Create a new, empty detector.
detector_t d3{host_mr};
check_empty_detector(d3);

// Move assign the filled detector to the empty one.
d3 = std::move(d2);
check_filled_detector(d3);
}
1 change: 1 addition & 0 deletions tests/unit_tests/cpu/simulation/particle_gun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using namespace detray;

using transform3_type = test::transform3;
using vector3 = test::vector3;

constexpr const scalar tol{1e-3f};

Expand Down
Loading

0 comments on commit c926d73

Please sign in to comment.