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