From 208948e26444a2311462779063577eaa66522427 Mon Sep 17 00:00:00 2001 From: Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch> Date: Wed, 18 Sep 2024 15:34:04 +0200 Subject: [PATCH] Introduced copy::get_size for SoA containers. --- core/include/vecmem/utils/copy.hpp | 7 ++++- core/include/vecmem/utils/impl/copy.ipp | 39 +++++++++++++++++++++++++ tests/common/soa_copy_tests.ipp | 12 ++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/core/include/vecmem/utils/copy.hpp b/core/include/vecmem/utils/copy.hpp index 12128d40..3ec76656 100644 --- a/core/include/vecmem/utils/copy.hpp +++ b/core/include/vecmem/utils/copy.hpp @@ -1,7 +1,7 @@ /* * VecMem project, 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 */ @@ -179,6 +179,11 @@ class VECMEM_CORE_EXPORT copy { edm::host<edm::schema<VARTYPES...>>& to, type::copy_type cptype = type::unknown) const; + /// Get the (outer) size of a resizable SoA container + template <typename... VARTYPES> + typename edm::view<edm::schema<VARTYPES...>>::size_type get_size( + const edm::view<edm::schema<VARTYPES...>>& data) const; + /// @} protected: diff --git a/core/include/vecmem/utils/impl/copy.ipp b/core/include/vecmem/utils/impl/copy.ipp index 3fce637f..5986cdf9 100644 --- a/core/include/vecmem/utils/impl/copy.ipp +++ b/core/include/vecmem/utils/impl/copy.ipp @@ -444,6 +444,45 @@ copy::event_type copy::operator()( return operator()(from_view, vecmem::get_data(to_vec), cptype); } +template <typename... VARTYPES> +typename edm::view<edm::schema<VARTYPES...>>::size_type copy::get_size( + const edm::view<edm::schema<VARTYPES...>>& data) const { + + // Start by taking the capacity of the container. + typename edm::view<edm::schema<VARTYPES...>>::size_type size = + data.capacity(); + + // If there are jagged vectors in the container and/or the container is not + // resizable, we're done. It is done in two separate if statements to avoid + // MSVC trying to be too smart, and giving a warning... + if constexpr (std::disjunction_v< + edm::type::details::is_jagged_vector<VARTYPES>...>) { + return size; + } else { + // All the rest is put into an else block, to avoid MSVC trying to be + // too smart, and giving a warning about unreachable code... + if (data.size().ptr() == nullptr) { + return size; + } + + // A small security check. + assert(data.size().size() == + sizeof(typename edm::view<edm::schema<VARTYPES...>>::size_type)); + + // Get the exact size of the container. + do_copy(sizeof(typename edm::view<edm::schema<VARTYPES...>>::size_type), + data.size().ptr(), &size, type::unknown); + // We have to wait for this to finish, since the "size" variable is + // not going to be available outside of this function. And + // asynchronous SYCL memory copies can happen from variables on the + // stack as well... + create_event()->wait(); + + // Return what we got. + return size; + } +} + template <typename TYPE> bool copy::copy_view_impl( const data::vector_view<std::add_const_t<TYPE>>& from_view, diff --git a/tests/common/soa_copy_tests.ipp b/tests/common/soa_copy_tests.ipp index e93f3440..05413d4a 100644 --- a/tests/common/soa_copy_tests.ipp +++ b/tests/common/soa_copy_tests.ipp @@ -52,6 +52,9 @@ void soa_copy_tests_base<CONTAINER>::host_to_fixed_device_to_host_direct() { vecmem::copy::type::host_to_device) ->wait(); + // Check the size of the device buffer. + EXPECT_EQ(input.size(), main_copy().get_size(device_buffer)); + // Create the target host container. typename CONTAINER::host target{host_mr()}; @@ -134,6 +137,9 @@ void soa_copy_tests_base<CONTAINER>::host_to_resizable_device_to_host() { vecmem::copy::type::host_to_device) ->wait(); + // Check the size of the device buffer. + EXPECT_EQ(input.size(), main_copy().get_size(device_buffer)); + // Create the target host container. typename CONTAINER::host target{host_mr()}; @@ -166,6 +172,9 @@ void soa_copy_tests_base< vecmem::copy::type::host_to_device) ->wait(); + // Check the size of the device buffer. + EXPECT_EQ(input.size(), main_copy().get_size(device_buffer1)); + // Create the (resizable) device buffer. typename CONTAINER::buffer device_buffer2; vecmem::testing::make_buffer(device_buffer2, main_mr(), host_mr(), @@ -176,6 +185,9 @@ void soa_copy_tests_base< vecmem::copy::type::device_to_device) ->wait(); + // Check the size of the device buffer. + EXPECT_EQ(input.size(), main_copy().get_size(device_buffer2)); + // Create the target host container. typename CONTAINER::host target{host_mr()};