File indexing completed on 2025-06-26 23:26:38
0001 #ifndef DataFormats_Portable_interface_PortableHostCollection_h
0002 #define DataFormats_Portable_interface_PortableHostCollection_h
0003
0004 #include <cassert>
0005 #include <optional>
0006
0007 #include <alpaka/alpaka.hpp>
0008
0009 #include "DataFormats/Common/interface/Uninitialized.h"
0010 #include "DataFormats/Portable/interface/PortableCollectionCommon.h"
0011 #include "HeterogeneousCore/AlpakaInterface/interface/config.h"
0012 #include "HeterogeneousCore/AlpakaInterface/interface/host.h"
0013 #include "HeterogeneousCore/AlpakaInterface/interface/memory.h"
0014
0015
0016 template <typename T>
0017 class PortableHostCollection {
0018 public:
0019 using Layout = T;
0020 using View = typename Layout::View;
0021 using ConstView = typename Layout::ConstView;
0022 using Descriptor = typename Layout::Descriptor;
0023 using ConstDescriptor = typename Layout::ConstDescriptor;
0024 using Buffer = cms::alpakatools::host_buffer<std::byte[]>;
0025 using ConstBuffer = cms::alpakatools::const_host_buffer<std::byte[]>;
0026
0027 PortableHostCollection() = delete;
0028
0029 explicit PortableHostCollection(edm::Uninitialized) noexcept {};
0030
0031 PortableHostCollection(int32_t elements, alpaka_common::DevHost const& host)
0032
0033 : buffer_{cms::alpakatools::make_host_buffer<std::byte[]>(Layout::computeDataSize(elements))},
0034 layout_{buffer_->data(), elements},
0035 view_{layout_} {
0036
0037 assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout::alignment == 0);
0038 }
0039
0040 template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0041 PortableHostCollection(int32_t elements, TQueue const& queue)
0042
0043 : buffer_{cms::alpakatools::make_host_buffer<std::byte[]>(queue, Layout::computeDataSize(elements))},
0044 layout_{buffer_->data(), elements},
0045 view_{layout_} {
0046
0047 assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout::alignment == 0);
0048 }
0049
0050
0051 PortableHostCollection(PortableHostCollection const&) = delete;
0052 PortableHostCollection& operator=(PortableHostCollection const&) = delete;
0053
0054
0055 PortableHostCollection(PortableHostCollection&&) = default;
0056 PortableHostCollection& operator=(PortableHostCollection&&) = default;
0057
0058
0059 ~PortableHostCollection() = default;
0060
0061
0062 View& view() { return view_; }
0063 ConstView const& view() const { return view_; }
0064 ConstView const& const_view() const { return view_; }
0065
0066 View& operator*() { return view_; }
0067 ConstView const& operator*() const { return view_; }
0068
0069 View* operator->() { return &view_; }
0070 ConstView const* operator->() const { return &view_; }
0071
0072
0073 Buffer buffer() { return *buffer_; }
0074 ConstBuffer buffer() const { return *buffer_; }
0075 ConstBuffer const_buffer() const { return *buffer_; }
0076
0077
0078 void zeroInitialise() {
0079 std::memset(std::data(*buffer_), 0x00, alpaka::getExtentProduct(*buffer_) * sizeof(std::byte));
0080 }
0081
0082 template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0083 void zeroInitialise(TQueue&& queue) {
0084 alpaka::memset(std::forward<TQueue>(queue), *buffer_, 0x00);
0085 }
0086
0087
0088 static void ROOTReadStreamer(PortableHostCollection* newObj, Layout& layout) {
0089
0090 newObj->~PortableHostCollection();
0091
0092 new (newObj) PortableHostCollection(layout.metadata().size(), cms::alpakatools::host());
0093
0094 newObj->layout_.ROOTReadStreamer(layout);
0095
0096 layout.ROOTStreamerCleaner();
0097 }
0098
0099
0100
0101 void deepCopy(ConstView const& view) { layout_.deepCopy(view); }
0102
0103
0104 template <typename TQueue>
0105 void deepCopy(ConstView const& view, TQueue& queue) {
0106 ConstDescriptor desc{view};
0107 Descriptor desc_{view_};
0108 _deepCopy<0>(desc_, desc, queue);
0109 }
0110
0111 private:
0112
0113 template <int I, typename TQueue>
0114 void _deepCopy(Descriptor& dest, ConstDescriptor const& src, TQueue& queue) {
0115 if constexpr (I < ConstDescriptor::num_cols) {
0116 assert(std::get<I>(dest.buff).size_bytes() == std::get<I>(src.buff).size_bytes());
0117 alpaka::memcpy(
0118 queue,
0119 alpaka::createView(alpaka::getDev(queue), std::get<I>(dest.buff).data(), std::get<I>(dest.buff).size()),
0120 alpaka::createView(alpaka::getDev(queue), std::get<I>(src.buff).data(), std::get<I>(src.buff).size()));
0121 _deepCopy<I + 1>(dest, src, queue);
0122 }
0123 }
0124
0125
0126 std::optional<Buffer> buffer_;
0127 Layout layout_;
0128 View view_;
0129 };
0130
0131
0132 template <typename T0, typename... Args>
0133 class PortableHostMultiCollection {
0134 template <typename T>
0135 static constexpr std::size_t count_t_ = portablecollection::typeCount<T, T0, Args...>;
0136
0137 template <typename T>
0138 static constexpr std::size_t index_t_ = portablecollection::typeIndex<T, T0, Args...>;
0139
0140 static constexpr std::size_t members_ = portablecollection::membersCount<T0, Args...>;
0141
0142 public:
0143 using Buffer = cms::alpakatools::host_buffer<std::byte[]>;
0144 using ConstBuffer = cms::alpakatools::const_host_buffer<std::byte[]>;
0145 using Implementation = portablecollection::CollectionImpl<0, T0, Args...>;
0146
0147 using SizesArray = std::array<int32_t, members_>;
0148
0149 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0150 using Layout = portablecollection::TypeResolver<Idx, T0, Args...>;
0151 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0152 using View = typename Layout<Idx>::View;
0153 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0154 using ConstView = typename Layout<Idx>::ConstView;
0155
0156 private:
0157 template <std::size_t Idx>
0158 using Leaf = portablecollection::CollectionLeaf<Idx, Layout<Idx>>;
0159
0160 template <std::size_t Idx>
0161 Leaf<Idx>& get() {
0162 return static_cast<Leaf<Idx>&>(impl_);
0163 }
0164
0165 template <std::size_t Idx>
0166 Leaf<Idx> const& get() const {
0167 return static_cast<Leaf<Idx> const&>(impl_);
0168 }
0169
0170 template <typename T>
0171 portablecollection::CollectionLeaf<index_t_<T>, T>& get() {
0172 return static_cast<portablecollection::CollectionLeaf<index_t_<T>, T>&>(impl_);
0173 }
0174
0175 template <typename T>
0176 const portablecollection::CollectionLeaf<index_t_<T>, T>& get() const {
0177 return static_cast<const portablecollection::CollectionLeaf<index_t_<T>, T>&>(impl_);
0178 }
0179
0180 static int32_t computeDataSize(const std::array<int32_t, members_>& sizes) {
0181 int32_t ret = 0;
0182 portablecollection::constexpr_for<0, members_>(
0183 [&sizes, &ret](auto i) { ret += Layout<i>::computeDataSize(sizes[i]); });
0184 return ret;
0185 }
0186
0187 public:
0188 PortableHostMultiCollection() = delete;
0189
0190 explicit PortableHostMultiCollection(edm::Uninitialized) noexcept {};
0191
0192 PortableHostMultiCollection(int32_t elements, alpaka_common::DevHost const& host)
0193
0194 : buffer_{cms::alpakatools::make_host_buffer<std::byte[]>(Layout<>::computeDataSize(elements))},
0195 impl_{buffer_->data(), elements} {
0196
0197 assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout<>::alignment == 0);
0198 static_assert(members_ == 1);
0199 }
0200
0201 template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0202 PortableHostMultiCollection(int32_t elements, TQueue const& queue)
0203
0204 : buffer_{cms::alpakatools::make_host_buffer<std::byte[]>(queue, Layout<>::computeDataSize(elements))},
0205 impl_{buffer_->data(), elements} {
0206
0207 assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout<>::alignment == 0);
0208 static_assert(members_ == 1);
0209 }
0210
0211 PortableHostMultiCollection(const std::array<int32_t, members_>& sizes, alpaka_common::DevHost const& host)
0212
0213 : buffer_{cms::alpakatools::make_host_buffer<std::byte[]>(computeDataSize(sizes))},
0214 impl_{buffer_->data(), sizes} {
0215
0216 portablecollection::constexpr_for<0, members_>(
0217 [&](auto i) { assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout<i>::alignment == 0); });
0218 constexpr auto alignment = Layout<0>::alignment;
0219 portablecollection::constexpr_for<1, members_>(
0220 [&alignment](auto i) { static_assert(alignment == Layout<i>::alignment); });
0221 }
0222
0223 template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0224 PortableHostMultiCollection(const std::array<int32_t, members_>& sizes, TQueue const& queue)
0225
0226 : buffer_{cms::alpakatools::make_host_buffer<std::byte[]>(queue, computeDataSize(sizes))},
0227 impl_{buffer_->data(), sizes} {
0228
0229 portablecollection::constexpr_for<0, members_>(
0230 [&](auto i) { assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout<i>::alignment == 0); });
0231 constexpr auto alignment = Layout<0>::alignment;
0232 portablecollection::constexpr_for<1, members_>(
0233 [&alignment](auto i) { static_assert(alignment == Layout<i>::alignment); });
0234 }
0235
0236
0237 PortableHostMultiCollection(PortableHostMultiCollection const&) = delete;
0238 PortableHostMultiCollection& operator=(PortableHostMultiCollection const&) = delete;
0239
0240
0241 PortableHostMultiCollection(PortableHostMultiCollection&&) = default;
0242 PortableHostMultiCollection& operator=(PortableHostMultiCollection&&) = default;
0243
0244
0245 ~PortableHostMultiCollection() = default;
0246
0247
0248 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0249 View<Idx>& view() {
0250 return get<Idx>().view_;
0251 }
0252
0253 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0254 ConstView<Idx> const& view() const {
0255 return get<Idx>().view_;
0256 }
0257
0258 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0259 ConstView<Idx> const& const_view() const {
0260 return get<Idx>().view_;
0261 }
0262
0263 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0264 View<Idx>& operator*() {
0265 return get<Idx>().view_;
0266 }
0267
0268 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0269 ConstView<Idx> const& operator*() const {
0270 return get<Idx>().view_;
0271 }
0272
0273 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0274 View<Idx>* operator->() {
0275 return &get<Idx>().view_;
0276 }
0277
0278 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0279 ConstView<Idx> const* operator->() const {
0280 return &get<Idx>().view_;
0281 }
0282
0283
0284 template <typename T>
0285 typename T::View& view() {
0286 return get<T>().view_;
0287 }
0288
0289 template <typename T>
0290 typename T::ConstView const& view() const {
0291 return get<T>().view_;
0292 }
0293
0294 template <typename T>
0295 typename T::ConstView const& const_view() const {
0296 return get<T>().view_;
0297 }
0298
0299 template <typename T>
0300 typename T::View& operator*() {
0301 return get<T>().view_;
0302 }
0303
0304 template <typename T>
0305 typename T::ConstView const& operator*() const {
0306 return get<T>().view_;
0307 }
0308
0309 template <typename T>
0310 typename T::View* operator->() {
0311 return &get<T>().view_;
0312 }
0313
0314 template <typename T>
0315 typename T::ConstView const* operator->() const {
0316 return &get<T>().view_;
0317 }
0318
0319
0320 Buffer buffer() { return *buffer_; }
0321 ConstBuffer buffer() const { return *buffer_; }
0322 ConstBuffer const_buffer() const { return *buffer_; }
0323
0324
0325 void zeroInitialise() {
0326 std::memset(std::data(*buffer_), 0x00, alpaka::getExtentProduct(*buffer_) * sizeof(std::byte));
0327 }
0328
0329 template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0330 void zeroInitialise(TQueue&& queue) {
0331 alpaka::memset(std::forward<TQueue>(queue), *buffer_, 0x00);
0332 }
0333
0334
0335 SizesArray sizes() const {
0336 SizesArray ret;
0337 portablecollection::constexpr_for<0, members_>([&](auto i) { ret[i] = get<i>().layout_.metadata().size(); });
0338 return ret;
0339 }
0340
0341
0342 static void ROOTReadStreamer(PortableHostMultiCollection* newObj, Implementation& onfileImpl) {
0343 newObj->~PortableHostMultiCollection();
0344
0345 std::array<int32_t, members_> sizes;
0346 portablecollection::constexpr_for<0, members_>([&sizes, &onfileImpl](auto i) {
0347 sizes[i] = static_cast<Leaf<i> const&>(onfileImpl).layout_.metadata().size();
0348 });
0349 new (newObj) PortableHostMultiCollection(sizes, cms::alpakatools::host());
0350 portablecollection::constexpr_for<0, members_>([&newObj, &onfileImpl](auto i) {
0351 static_cast<Leaf<i>&>(newObj->impl_).layout_.ROOTReadStreamer(static_cast<Leaf<i> const&>(onfileImpl).layout_);
0352 static_cast<Leaf<i>&>(onfileImpl).layout_.ROOTStreamerCleaner();
0353 });
0354 }
0355
0356 private:
0357 std::optional<Buffer> buffer_;
0358 Implementation impl_;
0359 };
0360
0361
0362
0363
0364 template <typename T0, typename T1>
0365 using PortableHostCollection2 = ::PortableHostMultiCollection<T0, T1>;
0366
0367 template <typename T0, typename T1, typename T2>
0368 using PortableHostCollection3 = ::PortableHostMultiCollection<T0, T1, T2>;
0369
0370 template <typename T0, typename T1, typename T2, typename T3>
0371 using PortableHostCollection4 = ::PortableHostMultiCollection<T0, T1, T2, T3>;
0372
0373 template <typename T0, typename T1, typename T2, typename T3, typename T4>
0374 using PortableHostCollection5 = ::PortableHostMultiCollection<T0, T1, T2, T3, T4>;
0375
0376 #endif