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/get_default_resource.hpp"
15#include "vecmem/utils/debug.hpp"
16#include "vecmem/utils/type_traits.hpp"
28template <
typename TYPE>
40 "Prepared a device vector buffer of capacity %u "
41 "for use on a device (ptr: %p)",
45template <
typename TYPE>
54template <
typename TYPE>
65 VECMEM_DEBUG_MSG(2,
"Set %u vector elements to %i at ptr: %p",
66 data.
capacity(), value,
static_cast<void*
>(data.
ptr()));
69template <
typename TYPE>
78template <
typename TYPE>
96template <
typename TYPE>
104template <
typename TYPE>
113template <
typename TYPE,
typename ALLOC>
133template <
typename TYPE,
typename ALLOC>
136 std::vector<TYPE, ALLOC>&
to_vec, type::copy_type
cptype)
const {
143template <
typename TYPE>
167template <
typename TYPE>
183 auto value = make_unique_alloc<value_type>(pinnedHostMr);
192template <
typename TYPE>
196 if (data.
size() == 0) {
202 if (data.
host_ptr()[0].size_ptr() !=
nullptr) {
220 "Prepared a jagged device vector buffer of size %u "
221 "for use on a device",
225template <
typename TYPE>
233template <
typename TYPE>
242 const std::size_t
total_size = std::accumulate(
244 static_cast<std::size_t
>(0
u),
246 return sum + iv.capacity();
249 for (std::size_t
i = 0;
i < data.
size(); ++
i) {
251 if ((
iv.capacity() != 0
u) && (
iv.ptr() !=
nullptr)) {
263 for (std::size_t
i = 0;
i < data.
size(); ++
i) {
270template <
typename TYPE>
279template <
typename TYPE>
306template <
typename TYPE>
315template <
typename TYPE>
324template <
typename TYPE,
typename ALLOC1,
typename ALLOC2>
345template <
typename TYPE,
typename ALLOC1,
typename ALLOC2>
349 type::copy_type
cptype)
const {
355template <
typename TYPE>
360 std::vector<typename data::vector_view<TYPE>::size_type>
result(data.
size(),
364 for (std::size_t
i = 0;
i < data.
size(); ++
i) {
367 if ((data.
host_ptr()[
i].capacity() != 0) &&
368 (data.
host_ptr()[
i].size_ptr() !=
nullptr)) {
386 for (std::size_t
i = 0;
i < data.
size(); ++
i) {
392template <
typename TYPE>
399 if ((
sizes.size() == 0) && (data.
size() == 0)) {
404 std::ostringstream
msg;
405 msg <<
"sizes.size() (" <<
sizes.size() <<
") != data.size() ("
406 << data.
size() <<
")";
407 throw std::length_error(
msg.str());
417 std::ostringstream
msg;
418 msg <<
"data.host_ptr()[" <<
i <<
"].capacity() ("
419 << data.
host_ptr()[
i].capacity() <<
") < sizes[" <<
i <<
"] ("
421 throw std::length_error(
msg.str());
425 if (data.
host_ptr()[
i].size_ptr() ==
nullptr) {
428 throw std::invalid_argument(
429 "Inconsistent target jagged vector view received for resizing");
442template <
typename TYPE>
452template <
typename TYPE>
453async_sizes<typename data::vector_view<TYPE>::size_type>
copy::get_sizes(
454 const data::jagged_vector_view<TYPE>& data,
455 memory_resource& pinnedHostMr)
const {
458 for (std::size_t i = 0; i < data.size(); ++i) {
461 if ((data.host_ptr()[i].capacity() != 0) &&
462 (data.host_ptr()[i].size_ptr() !=
nullptr)) {
465 vector<typename data::vector_view<TYPE>::size_type> result(
466 data.size(), 0, &pinnedHostMr);
471 data.host_ptr()[i].size_ptr(), result.data() + i,
480 vector<typename data::vector_view<TYPE>::size_type> result(data.size(), 0);
481 for (std::size_t i = 0; i < data.size(); ++i) {
482 result[i] = data.host_ptr()[i].capacity();
487template <
typename SCHEMA>
491 if (data.layout().ptr() != data.host_layout().ptr()) {
492 assert(data.layout().capacity() > 0
u);
494 copy_view_impl(data.host_layout(), data.layout(),
type::unknown);
499 if (data.size().ptr() !=
nullptr) {
500 assert(data.size().capacity() > 0
u);
501 do_memset(data.size().capacity() *
sizeof(
char), data.size().ptr(), 0);
504 "Prepared an SoA container of capacity %u "
505 "for use on a device (layout: {%u, %p}, size: {%u, %p})",
506 data.capacity(), data.layout().size(),
507 static_cast<void*
>(data.layout().ptr()),
508 data.size().size(),
static_cast<void*
>(data.size().ptr()));
511template <
typename SCHEMA>
519template <
typename... VARTYPES>
524 if (data.payload().ptr() !=
nullptr) {
541template <
typename... VARTYPES>
595 if ((
from_view.payload().ptr() !=
nullptr) &&
596 (
to_view.payload().ptr() !=
nullptr) &&
600 if (
from_view.payload().capacity() == 0) {
605 VECMEM_DEBUG_MSG(2,
"Performing simple SoA copy of %u bytes",
612 if (
to_view.size().ptr() !=
nullptr) {
617 std::ostringstream
msg;
618 msg <<
"from_view.size().capacity() ("
620 <<
") != to_view.size().capacity() ("
621 <<
to_view.size().capacity() <<
")";
622 throw std::length_error(
msg.str());
650template <
typename... VARTYPES,
template <
typename>
class INTERFACE>
670 type::copy_type
cptype)
const {
676template <
typename... VARTYPES>
684 value_type size = data.capacity();
689 if constexpr (std::disjunction_v<
695 if (data.size().ptr() ==
nullptr) {
700 assert(data.size().size() ==
sizeof(value_type));
726 if constexpr (std::disjunction_v<
730 *value = data.capacity();
735 if (data.size().ptr() ==
nullptr) {
738 make_unique_alloc<value_type>(*(get_default_resource()));
739 *value = data.capacity();
744 assert(data.size().size() ==
sizeof(value_type));
747 auto value = make_unique_alloc<value_type>(pinnedHostMr);
750 do_copy(
sizeof(value_type), data.size().ptr(), value.get(),
758template <
typename... VARTYPES>
765 "Function can only be used on containers with jagged vectors");
780template <
typename TYPE>
781bool copy::copy_view_impl(
782 const data::vector_view<std::add_const_t<TYPE>>& from_view,
783 data::vector_view<TYPE> to_view, type::copy_type cptype)
const {
786 const typename data::vector_view<std::add_const_t<TYPE>>::size_type size =
794 if (to_view.capacity() < size) {
795 std::ostringstream msg;
796 msg <<
"Target capacity (" << to_view.capacity() <<
") < source size ("
798 throw std::length_error(msg.str());
803 if (to_view.size_ptr() !=
nullptr) {
822 to_view.size_ptr(), size_cptype);
830 do_copy(size *
sizeof(TYPE), from_view.ptr(), to_view.ptr(), cptype);
834template <
typename TYPE>
835bool copy::copy_view_impl(
836 const data::jagged_vector_view<std::add_const_t<TYPE>>& from_view,
837 data::jagged_vector_view<TYPE> to_view, type::copy_type cptype)
const {
840 if (from_view.size() > to_view.size()) {
841 std::ostringstream msg;
842 msg <<
"from_view.size() (" << from_view.size()
843 <<
") > to_view.size() (" << to_view.size() <<
")";
844 throw std::length_error(msg.str());
848 const typename data::jagged_vector_view<std::add_const_t<TYPE>>::size_type
849 size = from_view.size();
855 const bool from_is_contiguous = is_contiguous(from_view.host_ptr(), size);
856 const bool to_is_contiguous = is_contiguous(to_view.host_ptr(), size);
857 VECMEM_DEBUG_MSG(3,
"from_is_contiguous = %d, to_is_contiguous = %d",
858 from_is_contiguous, to_is_contiguous);
867 auto set_sizes_event =
set_sizes(sizes, to_view);
871 std::vector<typename data::vector_view<std::add_const_t<TYPE>>::size_type>
873 bool capacities_match =
true;
874 for (std::size_t i = 0; i < size; ++i) {
875 if (from_view.host_ptr()[i].capacity() !=
876 to_view.host_ptr()[i].capacity()) {
877 capacities_match =
false;
880 capacities[i] = from_view.host_ptr()[i].capacity();
884 if (from_is_contiguous && to_is_contiguous && capacities_match) {
886 copy_views_contiguous_impl(capacities, from_view.host_ptr(),
887 to_view.host_ptr(), cptype);
892 copy_views_impl(sizes, from_view.host_ptr(), to_view.host_ptr(),
898 set_sizes_event->wait();
902template <
typename TYPE>
903void copy::copy_views_impl(
905 const data::vector_view<std::add_const_t<TYPE>>* from_view,
906 data::vector_view<TYPE>* to_view, type::copy_type cptype)
const {
909 assert(from_view !=
nullptr);
910 assert(to_view !=
nullptr);
913 const std::size_t size = sizes.size();
914 [[maybe_unused]] std::size_t copy_ops = 0;
917 for (std::size_t i = 0; i < size; ++i) {
925 assert(from_view[i].ptr() !=
nullptr);
926 assert(to_view[i].ptr() !=
nullptr);
927 assert(sizes[i] <= from_view[i].capacity());
928 assert(sizes[i] <= to_view[i].capacity());
931 do_copy(sizes[i] *
sizeof(TYPE), from_view[i].ptr(), to_view[i].ptr(),
938 "Copied the payload of a jagged vector of type "
939 "\"%s\" with %lu copy operation(s)",
940 typeid(TYPE).name(), copy_ops);
943template <
typename TYPE>
944void copy::copy_views_contiguous_impl(
946 const data::vector_view<std::add_const_t<TYPE>>* from_view,
947 data::vector_view<TYPE>* to_view, type::copy_type cptype)
const {
950 assert(from_view !=
nullptr);
951 assert(to_view !=
nullptr);
952 assert(is_contiguous(from_view, sizes.size()));
953 assert(is_contiguous(to_view, sizes.size()));
956 const std::size_t size = sizes.size();
957 const std::size_t total_size =
958 std::accumulate(sizes.begin(), sizes.end(),
959 static_cast<std::size_t
>(0)) *
963 for (std::size_t i = 0; i < size; ++i) {
971 assert(from_view[i].ptr() !=
nullptr);
972 assert(to_view[i].ptr() !=
nullptr);
975 do_copy(total_size, from_view[i].ptr(), to_view[i].ptr(), cptype);
981 "Copied the payload of a jagged vector of type "
982 "\"%s\" with 1 copy operation(s)",
983 typeid(TYPE).name());
986template <
typename TYPE>
987bool copy::is_contiguous(
const data::vector_view<TYPE>* data,
994 auto ptr = data[0].ptr();
995 for (std::size_t i = 1; i < size; ++i) {
996 if ((ptr + data[i - 1].capacity()) != data[i].ptr()) {
1004template <std::size_t INDEX,
typename... VARTYPES>
1005void copy::memset_impl(edm::view<edm::schema<VARTYPES...>> data,
1009 if constexpr (edm::type::details::is_scalar<
typename std::tuple_element<
1010 INDEX, std::tuple<VARTYPES...>>::type>::value) {
1011 do_memset(
sizeof(
typename std::tuple_element<
1012 INDEX, std::tuple<VARTYPES...>>::type::type),
1013 data.template get<INDEX>(), value);
1016 memset(data.template get<INDEX>(), value);
1019 if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
1020 memset_impl<INDEX + 1>(data, value);
1024template <std::size_t INDEX,
typename... VARTYPES,
1025 template <
typename>
class INTERFACE>
1026void copy::resize_impl(
1027 const edm::view<edm::details::add_const_t<edm::schema<VARTYPES...>>>&
1029 edm::host<edm::schema<VARTYPES...>, INTERFACE>& to_vec,
1030 [[maybe_unused]] type::copy_type cptype)
const {
1038 if constexpr (std::disjunction_v<
1039 edm::type::details::is_jagged_vector<VARTYPES>...> ==
1043 edm::details::add_const_t<edm::schema<VARTYPES...>>>::size_type
1044 size = from_view.capacity();
1046 if (from_view.size().ptr() !=
nullptr) {
1048 assert(from_view.size().size() ==
1049 sizeof(
typename edm::view<edm::details::add_const_t<
1050 edm::schema<VARTYPES...>>>::size_type));
1052 do_copy(
sizeof(
typename edm::view<edm::details::add_const_t<
1053 edm::schema<VARTYPES...>>>::size_type),
1054 from_view.size().ptr(), &size, cptype);
1062 VECMEM_DEBUG_MSG(4,
"Resizing a (non-jagged) container to size %u",
1064 to_vec.resize(size);
1069 if constexpr (edm::type::details::is_jagged_vector<
1070 typename std::tuple_element<
1071 INDEX, std::tuple<VARTYPES...>>::type>::value) {
1073 auto sizes =
get_sizes(from_view.template get<INDEX>());
1076 4,
"Resizing jagged vector variable at index %lu to size %lu",
1077 INDEX, sizes.size());
1081 for (std::size_t i = 0; i < sizes.size(); ++i) {
1082 to_vec.template get<INDEX>()[i].resize(sizes[i]);
1084 }
else if constexpr (edm::type::details::is_vector<
1085 typename std::tuple_element<
1087 std::tuple<VARTYPES...>>::type>::value) {
1089 auto size =
get_size(from_view.template get<INDEX>());
1092 "Resizing vector variable at index %lu to size %u",
1094 to_vec.template get<INDEX>().resize(size);
1097 if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
1098 resize_impl<INDEX + 1>(from_view, to_vec, cptype);
1103template <std::size_t INDEX,
typename... VARTYPES>
1104void copy::copy_sizes_impl(
1105 [[maybe_unused]]
const edm::view<
1106 edm::details::add_const_t<edm::schema<VARTYPES...>>>& from_view,
1107 [[maybe_unused]] edm::view<edm::schema<VARTYPES...>> to_view,
1108 [[maybe_unused]] type::copy_type cptype)
const {
1112 assert(to_view.size().ptr() !=
nullptr);
1113 assert(from_view.size().ptr() ==
nullptr);
1116 if constexpr (std::disjunction_v<
1117 edm::type::details::is_jagged_vector<VARTYPES>...> ==
1121 edm::details::add_const_t<edm::schema<VARTYPES...>>>::size_type
1122 size = from_view.capacity();
1138 do_copy(
sizeof(
typename edm::view<edm::details::add_const_t<
1139 edm::schema<VARTYPES...>>>::size_type),
1140 &size, to_view.size().ptr(), size_cptype);
1149 if constexpr (edm::type::details::is_jagged_vector<
1150 typename std::tuple_element<
1151 INDEX, std::tuple<VARTYPES...>>::type>::value) {
1153 const auto sizes =
get_sizes(from_view.template get<INDEX>());
1154 set_sizes(sizes, to_view.template get<INDEX>())->wait();
1157 if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
1158 copy_sizes_impl<INDEX + 1>(from_view, to_view, cptype);
1163template <std::size_t INDEX,
typename... VARTYPES>
1164void copy::copy_payload_impl(
1165 const edm::view<edm::details::add_const_t<edm::schema<VARTYPES...>>>&
1167 edm::view<edm::schema<VARTYPES...>> to_view, type::copy_type cptype)
const {
1170 if constexpr (edm::type::details::is_scalar<
typename std::tuple_element<
1171 INDEX, std::tuple<VARTYPES...>>::type>::value) {
1172 do_copy(
sizeof(
typename std::tuple_element<
1173 INDEX, std::tuple<VARTYPES...>>::type::type),
1174 from_view.template get<INDEX>(), to_view.template get<INDEX>(),
1178 copy_view_impl(from_view.template get<INDEX>(),
1179 to_view.template get<INDEX>(), cptype);
1182 if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
1183 copy_payload_impl<INDEX + 1>(from_view, to_view, cptype);
1187template <std::size_t INDEX,
typename... VARTYPES>
1188std::vector<data::vector_view<int>::size_type> copy::get_sizes_impl(
1189 const edm::view<edm::schema<VARTYPES...>>& view)
const {
1193 edm::details::has_jagged_vector<edm::schema<VARTYPES...>>::value,
1194 "Function can only be used on containers with jagged vectors");
1197 if constexpr (edm::type::details::is_jagged_vector<
1198 typename std::tuple_element<
1199 INDEX, std::tuple<VARTYPES...>>::type>::value) {
1201 return get_sizes(view.template get<INDEX>());
1202 }
else if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
1205 return get_sizes_impl<INDEX + 1>(view);
1209#if defined(__GNUC__)
1210 __builtin_unreachable();
1211#elif defined(_MSC_VER)
1216template <std::size_t INDEX,
typename... VARTYPES>
1217async_sizes<data::vector_view<int>::size_type> copy::get_sizes_impl(
1218 const edm::view<edm::schema<VARTYPES...>>& view,
1219 memory_resource& pinnedHostMr)
const {
1223 edm::details::has_jagged_vector<edm::schema<VARTYPES...>>::value,
1224 "Function can only be used on containers with jagged vectors");
1227 if constexpr (edm::type::details::is_jagged_vector<
1228 typename std::tuple_element<
1229 INDEX, std::tuple<VARTYPES...>>::type>::value) {
1231 return get_sizes(view.template get<INDEX>(), pinnedHostMr);
1232 }
else if constexpr (
sizeof...(VARTYPES) > (INDEX + 1)) {
1235 return get_sizes_impl<INDEX + 1>(view, pinnedHostMr);
1239#if defined(__GNUC__)
1240 __builtin_unreachable();
1241#elif defined(_MSC_VER)
An allocator class that wraps a memory resource.
Definition allocator.hpp:37
Return type for asynchronous size retrievals.
Definition async_size.hpp:25
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:43
std::unique_ptr< abstract_event > event_type
Event type used by the copy class.
Definition copy.hpp:82
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:144
virtual void do_memset(std::size_t size, void *ptr, int value) const
Perform a "low level" memory filling operation.
Definition copy.cpp:56
virtual VECMEM_NODISCARD event_type create_event() const
Create an event for synchronization.
Definition copy.cpp:66
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:356
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:79
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
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
Technical base type for buffer<schema<VARTYPES...>>
Definition buffer.hpp:28
Technical base type for host<schema<VARTYPES...>,INTERFACE>
Definition host.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:215
Main namespace for the vecmem classes/functions.
Definition atomic_ref.hpp:16
constexpr ignore_event_t ignore_event
Constant object of type ignore_event_t to use as an argument for functions that do not need to return...
Definition copy.hpp:42
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:65
@ device_to_host
Copy operation between a device and the host.
Definition copy.hpp:69
@ device_to_device
Copy operation between two devices.
Definition copy.hpp:73
@ unknown
Unknown copy type, determined at runtime.
Definition copy.hpp:75
@ host_to_host
Copy operation on the host.
Definition copy.hpp:71
@ host_to_device
Copy operation between the host and a device.
Definition copy.hpp:67
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
Tag type to indicate overloads of functions that do not need to return an event.
Definition copy.hpp:37