11#include "vecmem/containers/details/resize_jagged_vector.hpp"
12#include "vecmem/containers/jagged_vector.hpp"
13#include "vecmem/edm/details/schema_traits.hpp"
14#include "vecmem/memory/host_memory_resource.hpp"
15#include "vecmem/utils/debug.hpp"
16#include "vecmem/utils/type_traits.hpp"
28template <
typename TYPE>
32 if ((data.size_ptr() ==
nullptr) || (data.capacity() == 0)) {
40 "Prepared a device vector buffer of capacity %u "
41 "for use on a device (ptr: %p)",
42 data.capacity(),
static_cast<void*
>(data.size_ptr()));
48template <
typename TYPE>
52 if (data.capacity() == 0) {
57 do_memset(data.capacity() *
sizeof(TYPE), data.ptr(), value);
58 VECMEM_DEBUG_MSG(2,
"Set %u vector elements to %i at ptr: %p",
59 data.capacity(), value,
static_cast<void*
>(data.ptr()));
65template <
typename TYPE>
83template <
typename TYPE>
97template <
typename TYPE,
typename ALLOC>
99 const data::vector_view<std::add_const_t<TYPE>>& from_view,
100 std::vector<TYPE, ALLOC>& to_vec, type::copy_type cptype)
const {
103 const typename data::vector_view<std::add_const_t<TYPE>>::size_type size =
114 do_copy(size *
sizeof(TYPE), from_view.ptr(), to_vec.data(), cptype);
120template <
typename TYPE>
144template <
typename TYPE>
148 if (data.
size() == 0) {
154 if (data.
host_ptr()[0].size_ptr() !=
nullptr) {
172 "Prepared a jagged device vector buffer of size %lu "
173 "for use on a device",
180template <
typename TYPE>
185 if (is_contiguous(data.host_ptr(), data.capacity())) {
189 const std::size_t total_size = std::accumulate(
190 data.host_ptr(), data.host_ptr() + data.size(),
191 static_cast<std::size_t
>(0u),
192 [](std::size_t sum,
const data::vector_view<TYPE>& iv) {
193 return sum + iv.capacity();
196 for (std::size_t i = 0; i < data.size(); ++i) {
197 data::vector_view<TYPE>& iv = data.host_ptr()[i];
198 if ((iv.capacity() != 0u) && (iv.ptr() !=
nullptr)) {
200 do_memset(total_size *
sizeof(TYPE), iv.ptr(), value);
210 for (std::size_t i = 0; i < data.size(); ++i) {
211 data::vector_view<TYPE>& iv = data.host_ptr()[i];
212 do_memset(iv.capacity() *
sizeof(TYPE), iv.ptr(), value);
220template <
typename TYPE>
247template <
typename TYPE>
261template <
typename TYPE,
typename ALLOC1,
typename ALLOC2>
263 const data::jagged_vector_view<std::add_const_t<TYPE>>& from_view,
264 std::vector<std::vector<TYPE, ALLOC2>, ALLOC1>& to_vec,
265 type::copy_type cptype)
const {
270 assert(sizes.size() == to_vec.size());
271 for (
typename data::jagged_vector_view<std::add_const_t<TYPE>>::size_type
273 i < from_view.size(); ++i) {
274 to_vec[i].resize(sizes[i]);
281template <
typename TYPE>
289template <
typename TYPE>
295 if ((
sizes.size() == 0) && (data.
size() == 0)) {
299 if (sizes.size() != data.
size()) {
300 std::ostringstream msg;
301 msg <<
"sizes.size() (" << sizes.size() <<
") != data.size() ("
302 << data.
size() <<
")";
303 throw std::length_error(msg.str());
307 bool perform_copy =
true;
309 i < data.
size(); ++i) {
312 if (data.
host_ptr()[i].capacity() < sizes[i]) {
313 std::ostringstream msg;
314 msg <<
"data.host_ptr()[" << i <<
"].capacity() ("
315 << data.
host_ptr()[i].capacity() <<
") < sizes[" << i <<
"] ("
317 throw std::length_error(msg.str());
321 if (data.
host_ptr()[i].size_ptr() ==
nullptr) {
322 perform_copy =
false;
323 }
else if (perform_copy ==
false) {
324 throw std::invalid_argument(
325 "Inconsistent target jagged vector view received for resizing");
329 if (perform_copy ==
false) {
341template <
typename SCHEMA>
345 if (data.capacity() == 0) {
350 if (data.layout().ptr() != data.host_layout().ptr()) {
351 assert(data.layout().capacity() > 0u);
352 [[maybe_unused]]
bool did_copy =
353 copy_view_impl(data.host_layout(), data.layout(),
type::unknown);
358 if (data.size().ptr() !=
nullptr) {
359 assert(data.size().capacity() > 0u);
360 do_memset(data.size().capacity() *
sizeof(
char), data.size().ptr(), 0);
363 "Prepared an SoA container of capacity %u "
364 "for use on a device (layout: {%u, %p}, size: {%u, %p})",
365 data.capacity(), data.layout().size(),
366 static_cast<void*
>(data.layout().ptr()),
367 data.size().size(),
static_cast<void*
>(data.size().ptr()));
373template <
typename... VARTYPES>
378 if (data.payload().ptr() !=
nullptr) {
379 memset(data.payload(), value);
382 memset_impl<0>(data, value);
389template <
typename... VARTYPES>
442 if ((
from_view.payload().ptr() !=
nullptr) &&
443 (
to_view.payload().ptr() !=
nullptr) &&
447 if (
from_view.payload().capacity() == 0) {
452 VECMEM_DEBUG_MSG(2,
"Performing simple SoA copy of %u bytes",
453 from_view.payload().size());
456 copy_view_impl(from_view.payload(), to_view.payload(), cptype);
459 if (to_view.
size().ptr() !=
nullptr) {
461 if (from_view.size().ptr() !=
nullptr) {
463 if (from_view.size().capacity() != to_view.
size().capacity()) {
464 std::ostringstream msg;
465 msg <<
"from_view.size().capacity() ("
466 << from_view.size().capacity()
467 <<
") != to_view.size().capacity() ("
468 << to_view.
size().capacity() <<
")";
469 throw std::length_error(msg.str());
472 copy_view_impl(from_view.size(), to_view.
size(), cptype);
475 copy_sizes_impl<0>(from_view, to_view, cptype);
484 copy_payload_impl<0>(from_view, to_view, cptype);
490template <
typename... VARTYPES,
template <
typename>
class INTERFACE>
492 const edm::view<edm::details::add_const_t<edm::schema<VARTYPES...>>>&
494 edm::host<edm::schema<VARTYPES...>, INTERFACE>& to_vec,
495 type::copy_type cptype)
const {
498 resize_impl<0>(from_view, to_vec, cptype);
504template <
typename... VARTYPES>
515 if constexpr (std::disjunction_v<
521 if (data.size().ptr() ==
nullptr) {
526 assert(data.size().size() ==
550 "Function can only be used on containers with jagged vectors");
556template <
typename TYPE>
557bool copy::copy_view_impl(
571 std::ostringstream msg;
572 msg <<
"Target capacity (" << to_view.
capacity() <<
") < source size ("
574 throw std::length_error(msg.str());
579 if (to_view.
size_ptr() !=
nullptr) {
606 do_copy(size *
sizeof(TYPE), from_view.ptr(), to_view.
ptr(), cptype);
610template <
typename TYPE>
611bool copy::copy_view_impl(
612 const data::jagged_vector_view<std::add_const_t<TYPE>>& from_view,
613 data::jagged_vector_view<TYPE> to_view, type::copy_type cptype)
const {
616 if (from_view.size() > to_view.size()) {
617 std::ostringstream msg;
618 msg <<
"from_view.size() (" << from_view.size()
619 <<
") > to_view.size() (" << to_view.size() <<
")";
620 throw std::length_error(msg.str());
624 const typename data::jagged_vector_view<std::add_const_t<TYPE>>::size_type
625 size = from_view.
size();
631 const bool from_is_contiguous = is_contiguous(from_view.host_ptr(), size);
632 const bool to_is_contiguous = is_contiguous(to_view.host_ptr(), size);
633 VECMEM_DEBUG_MSG(3,
"from_is_contiguous = %d, to_is_contiguous = %d",
634 from_is_contiguous, to_is_contiguous);
643 auto set_sizes_event =
set_sizes(sizes, to_view);
647 std::vector<typename data::vector_view<std::add_const_t<TYPE>>::size_type>
649 bool capacities_match =
true;
650 for (std::size_t i = 0; i < size; ++i) {
651 if (from_view.host_ptr()[i].capacity() !=
652 to_view.host_ptr()[i].capacity()) {
653 capacities_match =
false;
656 capacities[i] = from_view.host_ptr()[i].capacity();
660 if (from_is_contiguous && to_is_contiguous && capacities_match) {
662 copy_views_contiguous_impl(capacities, from_view.host_ptr(),
663 to_view.host_ptr(), cptype);
668 copy_views_impl(sizes, from_view.host_ptr(), to_view.host_ptr(),
674 set_sizes_event->wait();
678template <
typename TYPE>
679void copy::copy_views_impl(
681 const data::vector_view<std::add_const_t<TYPE>>* from_view,
682 data::vector_view<TYPE>* to_view, type::copy_type cptype)
const {
685 assert(from_view !=
nullptr);
686 assert(to_view !=
nullptr);
689 const std::size_t size = sizes.size();
690 [[maybe_unused]] std::size_t copy_ops = 0;
693 for (std::size_t i = 0; i < size; ++i) {
701 assert(from_view[i].ptr() !=
nullptr);
702 assert(to_view[i].ptr() !=
nullptr);
703 assert(sizes[i] <= from_view[i].capacity());
704 assert(sizes[i] <= to_view[i].capacity());
707 do_copy(sizes[i] *
sizeof(TYPE), from_view[i].ptr(), to_view[i].ptr(),
714 "Copied the payload of a jagged vector of type "
715 "\"%s\" with %lu copy operation(s)",
716 typeid(TYPE).name(), copy_ops);
719template <
typename TYPE>
720void copy::copy_views_contiguous_impl(
722 const data::vector_view<std::add_const_t<TYPE>>* from_view,
723 data::vector_view<TYPE>* to_view, type::copy_type cptype)
const {
726 assert(from_view !=
nullptr);
727 assert(to_view !=
nullptr);
728 assert(is_contiguous(from_view, sizes.size()));
729 assert(is_contiguous(to_view, sizes.size()));
732 const std::size_t size = sizes.size();
733 const std::size_t total_size =
734 std::accumulate(sizes.begin(), sizes.end(),
735 static_cast<std::size_t
>(0)) *
739 for (std::size_t i = 0; i < size; ++i) {
747 assert(from_view[i].ptr() !=
nullptr);
748 assert(to_view[i].ptr() !=
nullptr);
751 do_copy(total_size, from_view[i].ptr(), to_view[i].ptr(), cptype);
757 "Copied the payload of a jagged vector of type "
758 "\"%s\" with 1 copy operation(s)",
759 typeid(TYPE).name());
762template <
typename TYPE>
763std::vector<typename data::vector_view<TYPE>::size_type> copy::get_sizes_impl(
764 const data::vector_view<TYPE>* data, std::size_t size)
const {
767 std::vector<typename data::vector_view<TYPE>::size_type> result(size, 0);
770 for (std::size_t i = 0; i < size; ++i) {
773 if ((data[i].capacity() != 0) && (data[i].size_ptr() !=
nullptr)) {
790 for (std::size_t i = 0; i < size; ++i) {
791 result[i] = data[i].capacity();
796template <
typename TYPE>
797bool copy::is_contiguous(
const data::vector_view<TYPE>* data,
804 auto ptr = data[0].ptr();
805 for (std::size_t i = 1; i < size; ++i) {
806 if ((ptr + data[i - 1].capacity()) != data[i].ptr()) {
814template <std::size_t INDEX,
typename... VARTYPES>
815void copy::memset_impl(edm::view<edm::schema<VARTYPES...>> data,
819 if constexpr (edm::type::details::is_scalar<
typename std::tuple_element<
820 INDEX, std::tuple<VARTYPES...>>::type>::value) {
821 do_memset(
sizeof(
typename std::tuple_element<
822 INDEX, std::tuple<VARTYPES...>>::type::type),
823 data.template get<INDEX>(), value);
826 memset(data.template get<INDEX>(), value);
829 if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
830 memset_impl<INDEX + 1>(data, value);
834template <std::size_t INDEX,
typename... VARTYPES,
835 template <
typename>
class INTERFACE>
836void copy::resize_impl(
837 const edm::view<edm::details::add_const_t<edm::schema<VARTYPES...>>>&
839 edm::host<edm::schema<VARTYPES...>, INTERFACE>& to_vec,
840 [[maybe_unused]] type::copy_type cptype)
const {
848 if constexpr (std::disjunction_v<
849 edm::type::details::is_jagged_vector<VARTYPES>...> ==
853 edm::details::add_const_t<edm::schema<VARTYPES...>>>::size_type
854 size = from_view.capacity();
856 if (from_view.size().ptr() !=
nullptr) {
858 assert(from_view.size().size() ==
859 sizeof(
typename edm::view<edm::details::add_const_t<
860 edm::schema<VARTYPES...>>>::size_type));
862 do_copy(
sizeof(
typename edm::view<edm::details::add_const_t<
863 edm::schema<VARTYPES...>>>::size_type),
864 from_view.size().ptr(), &size, cptype);
872 VECMEM_DEBUG_MSG(4,
"Resizing a (non-jagged) container to size %u",
879 if constexpr (edm::type::details::is_jagged_vector<
880 typename std::tuple_element<
881 INDEX, std::tuple<VARTYPES...>>::type>::value) {
883 auto sizes =
get_sizes(from_view.template get<INDEX>());
886 4,
"Resizing jagged vector variable at index %lu to size %lu",
887 INDEX, sizes.size());
891 for (std::size_t i = 0; i < sizes.size(); ++i) {
892 to_vec.template get<INDEX>()[i].resize(sizes[i]);
894 }
else if constexpr (edm::type::details::is_vector<
895 typename std::tuple_element<
897 std::tuple<VARTYPES...>>::type>::value) {
899 auto size =
get_size(from_view.template get<INDEX>());
902 "Resizing vector variable at index %lu to size %u",
904 to_vec.template get<INDEX>().resize(size);
907 if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
908 resize_impl<INDEX + 1>(from_view, to_vec, cptype);
913template <std::size_t INDEX,
typename... VARTYPES>
914void copy::copy_sizes_impl(
915 [[maybe_unused]]
const edm::view<
916 edm::details::add_const_t<edm::schema<VARTYPES...>>>& from_view,
917 [[maybe_unused]] edm::view<edm::schema<VARTYPES...>> to_view,
918 [[maybe_unused]] type::copy_type cptype)
const {
922 assert(to_view.size().ptr() !=
nullptr);
923 assert(from_view.size().ptr() ==
nullptr);
926 if constexpr (std::disjunction_v<
927 edm::type::details::is_jagged_vector<VARTYPES>...> ==
931 edm::details::add_const_t<edm::schema<VARTYPES...>>>::size_type
932 size = from_view.capacity();
948 do_copy(
sizeof(
typename edm::view<edm::details::add_const_t<
949 edm::schema<VARTYPES...>>>::size_type),
950 &size, to_view.size().ptr(), size_cptype);
959 if constexpr (edm::type::details::is_jagged_vector<
960 typename std::tuple_element<
961 INDEX, std::tuple<VARTYPES...>>::type>::value) {
963 const auto sizes =
get_sizes(from_view.template get<INDEX>());
964 set_sizes(sizes, to_view.template get<INDEX>())->wait();
967 if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
968 copy_sizes_impl<INDEX + 1>(from_view, to_view, cptype);
973template <std::size_t INDEX,
typename... VARTYPES>
974void copy::copy_payload_impl(
975 const edm::view<edm::details::add_const_t<edm::schema<VARTYPES...>>>&
977 edm::view<edm::schema<VARTYPES...>> to_view, type::copy_type cptype)
const {
980 if constexpr (edm::type::details::is_scalar<
typename std::tuple_element<
981 INDEX, std::tuple<VARTYPES...>>::type>::value) {
982 do_copy(
sizeof(
typename std::tuple_element<
983 INDEX, std::tuple<VARTYPES...>>::type::type),
984 from_view.template get<INDEX>(), to_view.template get<INDEX>(),
988 copy_view_impl(from_view.template get<INDEX>(),
989 to_view.template get<INDEX>(), cptype);
992 if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
993 copy_payload_impl<INDEX + 1>(from_view, to_view, cptype);
997template <std::size_t INDEX,
typename... VARTYPES>
998std::vector<data::vector_view<int>::size_type> copy::get_sizes_impl(
999 const edm::view<edm::schema<VARTYPES...>>& view)
const {
1003 edm::details::has_jagged_vector<edm::schema<VARTYPES...>>::value,
1004 "Function can only be used on containers with jagged vectors");
1007 if constexpr (edm::type::details::is_jagged_vector<
1008 typename std::tuple_element<
1009 INDEX, std::tuple<VARTYPES...>>::type>::value) {
1011 return get_sizes(view.template get<INDEX>());
1012 }
else if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
1015 return get_sizes_impl<INDEX + 1>(view);
1019#if defined(__GNUC__)
1020 __builtin_unreachable();
1021#elif defined(_MSC_VER)
An allocator class that wraps a memory resource.
Definition allocator.hpp:37
VECMEM_NODISCARD event_type set_sizes(const std::vector< typename data::vector_view< TYPE >::size_type > &sizes, data::jagged_vector_view< TYPE > data) const
Helper function for setting the sizes of a resizable jagged vector.
VECMEM_NODISCARD event_type operator()(const data::vector_view< std::add_const_t< TYPE > > &from, data::vector_view< TYPE > to, type::copy_type cptype=type::unknown) const
Copy a 1-dimensional vector's data between two existing memory blocks.
VECMEM_NODISCARD event_type setup(data::vector_view< TYPE > data) const
Set up the internal state of a vector buffer correctly on a device.
virtual void do_copy(std::size_t size, const void *from, void *to, type::copy_type cptype) const
Perform a "low level" memory copy.
Definition copy.cpp:31
std::unique_ptr< abstract_event > event_type
Event type used by the copy class.
Definition copy.hpp:70
data::vector_view< TYPE >::size_type get_size(const data::vector_view< TYPE > &data) const
Helper function for getting the size of a resizable 1D buffer.
Definition copy.ipp:121
virtual void do_memset(std::size_t size, void *ptr, int value) const
Perform a "low level" memory filling operation.
Definition copy.cpp:44
virtual VECMEM_NODISCARD event_type create_event() const
Create an event for synchronization.
Definition copy.cpp:54
std::vector< typename data::vector_view< TYPE >::size_type > get_sizes(const data::jagged_vector_view< TYPE > &data) const
Helper function for getting the sizes of a resizable jagged vector.
Definition copy.ipp:282
VECMEM_NODISCARD event_type memset(data::vector_view< TYPE > data, int value) const
Set all bytes of the vector to some value.
data::vector_buffer< std::remove_cv_t< TYPE > > to(const data::vector_view< TYPE > &data, memory_resource &resource, type::copy_type cptype=type::unknown) const
Copy a 1-dimensional vector to the specified memory resource.
Definition copy.ipp:66
Object owning all the data of a jagged vector.
Definition jagged_vector_buffer.hpp:30
typename base_type::value_type value_type
Use the base class's value_type.
Definition jagged_vector_buffer.hpp:38
A view for jagged vectors.
Definition jagged_vector_view.hpp:45
VECMEM_HOST_AND_DEVICE pointer host_ptr() const
Access the host accessible array describing the inner vectors.
Definition jagged_vector_view.ipp:105
std::size_t size_type
We cannot use boolean types.
Definition jagged_vector_view.hpp:53
VECMEM_HOST_AND_DEVICE size_type capacity() const
Get the maximum capacity of the "outer" vector.
Definition jagged_vector_view.ipp:92
VECMEM_HOST_AND_DEVICE pointer ptr() const
Get a pointer to the vector elements.
Definition jagged_vector_view.ipp:99
VECMEM_HOST_AND_DEVICE size_type size() const
Get the "outer" size of the jagged vector.
Definition jagged_vector_view.ipp:86
Object owning the data held by it.
Definition vector_buffer.hpp:29
typename base_type::size_type size_type
Size type definition coming from the base class.
Definition vector_buffer.hpp:35
Class holding data about a 1 dimensional vector/array.
Definition vector_view.hpp:38
VECMEM_HOST_AND_DEVICE pointer ptr() const
Get a pointer to the vector elements.
Definition vector_view.ipp:91
unsigned int size_type
We cannot use boolean types.
Definition vector_view.hpp:47
VECMEM_HOST_AND_DEVICE size_pointer size_ptr() const
Get a pointer to the size of the vector.
Definition vector_view.ipp:84
VECMEM_HOST_AND_DEVICE size_type capacity() const
Get the maximum capacity of the vector.
Definition vector_view.ipp:78
VECMEM_HOST_AND_DEVICE size_type size() const
Get the size of the vector.
Definition vector_view.ipp:72
Technical base type for buffer<schema<VARTYPES...>>
Definition buffer.hpp:28
Technical base type for view<schema<VARTYPES...>>
Definition view.hpp:29
VECMEM_HOST std::vector< typename vector_view< T >::size_type > get_capacities(const jagged_vector_view< T > &data)
Get the capacities of the inner vectors of a jagged vector.
Definition jagged_vector_view.ipp:111
buffer_type
"Overall type" for a buffer object
Definition buffer_type.hpp:13
@ fixed_size
The buffer has a fixed number of elements.
@ resizable
The buffer is resizable/expandable.
void resize_jagged_vector(std::vector< std::vector< T, ALLOC1 >, ALLOC2 > &vec, std::size_t size)
Resize a generic jagged vector.
Definition resize_jagged_vector.hpp:23
VECMEM_HOST std::vector< vecmem::data::vector_view< int >::size_type > get_capacities(const view< schema< VARTYPES... > > &soa)
Helper function to get the capacities of the jagged vectors in a view.
Definition view.ipp:198
Main namespace for the vecmem classes/functions.
Definition atomic_ref.hpp:16
VECMEM_HOST data::vector_view< T > get_data(array< T, N > &a)
Helper function creating a vecmem::data::vector_view object.
Definition array.ipp:217
copy_type
Types of memory copies to handle.
Definition copy.hpp:53
@ device_to_host
Copy operation between a device and the host.
Definition copy.hpp:57
@ device_to_device
Copy operation between two devices.
Definition copy.hpp:61
@ unknown
Unknown copy type, determined at runtime.
Definition copy.hpp:63
@ host_to_host
Copy operation on the host.
Definition copy.hpp:59
@ host_to_device
Copy operation between the host and a device.
Definition copy.hpp:55
Technical base type for has_jagged_vector<schema<VARTYPES...>>
Definition schema_traits.hpp:238
Meta type describing the "schema" of an SoA container.
Definition schema.hpp:46
Definition schema_traits.hpp:108