File indexing completed on 2024-12-12 03:12:12
0001 #ifndef DataFormats_Portable_interface_PortableDeviceCollection_h
0002 #define DataFormats_Portable_interface_PortableDeviceCollection_h
0003
0004 #include <cassert>
0005 #include <optional>
0006 #include <type_traits>
0007
0008 #include <alpaka/alpaka.hpp>
0009
0010 #include "DataFormats/Common/interface/Uninitialized.h"
0011 #include "DataFormats/Portable/interface/PortableCollectionCommon.h"
0012 #include "HeterogeneousCore/AlpakaInterface/interface/config.h"
0013 #include "HeterogeneousCore/AlpakaInterface/interface/memory.h"
0014
0015
0016 template <typename T, typename TDev, typename = std::enable_if_t<alpaka::isDevice<TDev>>>
0017 class PortableDeviceCollection {
0018 static_assert(not std::is_same_v<TDev, alpaka_common::DevHost>,
0019 "Use PortableHostCollection<T> instead of PortableDeviceCollection<T, DevHost>");
0020
0021 public:
0022 using Layout = T;
0023 using View = typename Layout::View;
0024 using ConstView = typename Layout::ConstView;
0025 using Buffer = cms::alpakatools::device_buffer<TDev, std::byte[]>;
0026 using ConstBuffer = cms::alpakatools::const_device_buffer<TDev, std::byte[]>;
0027
0028 PortableDeviceCollection() = delete;
0029
0030 explicit PortableDeviceCollection(edm::Uninitialized) noexcept {}
0031
0032 PortableDeviceCollection(int32_t elements, TDev const& device)
0033 : buffer_{cms::alpakatools::make_device_buffer<std::byte[]>(device, 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 PortableDeviceCollection(int32_t elements, TQueue const& queue)
0042 : buffer_{cms::alpakatools::make_device_buffer<std::byte[]>(queue, Layout::computeDataSize(elements))},
0043 layout_{buffer_->data(), elements},
0044 view_{layout_} {
0045
0046 assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout::alignment == 0);
0047 }
0048
0049
0050 PortableDeviceCollection(PortableDeviceCollection const&) = delete;
0051 PortableDeviceCollection& operator=(PortableDeviceCollection const&) = delete;
0052
0053
0054 PortableDeviceCollection(PortableDeviceCollection&&) = default;
0055 PortableDeviceCollection& operator=(PortableDeviceCollection&&) = default;
0056
0057
0058 ~PortableDeviceCollection() = default;
0059
0060
0061 View& view() { return view_; }
0062 ConstView const& view() const { return view_; }
0063 ConstView const& const_view() const { return view_; }
0064
0065 View& operator*() { return view_; }
0066 ConstView const& operator*() const { return view_; }
0067
0068 View* operator->() { return &view_; }
0069 ConstView const* operator->() const { return &view_; }
0070
0071
0072 Buffer buffer() { return *buffer_; }
0073 ConstBuffer buffer() const { return *buffer_; }
0074 ConstBuffer const_buffer() const { return *buffer_; }
0075
0076
0077 template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0078 void zeroInitialise(TQueue&& queue) {
0079 alpaka::memset(std::forward<TQueue>(queue), *buffer_, 0x00);
0080 }
0081
0082 private:
0083 std::optional<Buffer> buffer_;
0084 Layout layout_;
0085 View view_;
0086 };
0087
0088
0089 template <typename TDev, typename T0, typename... Args>
0090 class PortableDeviceMultiCollection {
0091
0092 static_assert(not std::is_same_v<TDev, alpaka_common::DevHost>,
0093 "Use PortableHostCollection<T> instead of PortableDeviceCollection<T, DevHost>");
0094
0095 template <typename T>
0096 static constexpr std::size_t count_t_ = portablecollection::typeCount<T, T0, Args...>;
0097
0098 template <typename T>
0099 static constexpr std::size_t index_t_ = portablecollection::typeIndex<T, T0, Args...>;
0100
0101 static constexpr std::size_t members_ = sizeof...(Args) + 1;
0102
0103 public:
0104 using Buffer = cms::alpakatools::device_buffer<TDev, std::byte[]>;
0105 using ConstBuffer = cms::alpakatools::const_device_buffer<TDev, std::byte[]>;
0106 using Implementation = portablecollection::CollectionImpl<0, T0, Args...>;
0107
0108 using SizesArray = std::array<int32_t, members_>;
0109
0110 template <std::size_t Idx = 0>
0111 using Layout = portablecollection::TypeResolver<Idx, T0, Args...>;
0112
0113
0114
0115
0116 template <std::size_t Idx = 0UL>
0117 using View = typename std::tuple_element<Idx, std::tuple<T0, Args...>>::type::View;
0118
0119
0120
0121
0122 template <std::size_t Idx = 0UL>
0123 using ConstView = typename std::tuple_element<Idx, std::tuple<T0, Args...>>::type::ConstView;
0124
0125 private:
0126 template <std::size_t Idx>
0127 using Leaf = portablecollection::CollectionLeaf<Idx, Layout<Idx>>;
0128
0129 template <std::size_t Idx>
0130 Leaf<Idx>& get() {
0131 return static_cast<Leaf<Idx>&>(impl_);
0132 }
0133
0134 template <std::size_t Idx>
0135 Leaf<Idx> const& get() const {
0136 return static_cast<Leaf<Idx> const&>(impl_);
0137 }
0138
0139 template <typename T>
0140 Leaf<index_t_<T>>& get() {
0141 return static_cast<Leaf<index_t_<T>>&>(impl_);
0142 }
0143
0144 template <typename T>
0145 Leaf<index_t_<T>> const& get() const {
0146 return static_cast<Leaf<index_t_<T>> const&>(impl_);
0147 }
0148
0149 public:
0150 PortableDeviceMultiCollection() = delete;
0151
0152 explicit PortableDeviceMultiCollection(edm::Uninitialized) noexcept {};
0153
0154 PortableDeviceMultiCollection(int32_t elements, TDev const& device)
0155 : buffer_{cms::alpakatools::make_device_buffer<std::byte[]>(device, Layout<>::computeDataSize(elements))},
0156 impl_{buffer_->data(), elements} {
0157
0158 assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout<>::alignment == 0);
0159 static_assert(members_ == 1);
0160 }
0161
0162 template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0163 PortableDeviceMultiCollection(int32_t elements, TQueue const& queue)
0164 : buffer_{cms::alpakatools::make_device_buffer<std::byte[]>(queue, Layout<>::computeDataSize(elements))},
0165 impl_{buffer_->data(), elements} {
0166
0167 assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout<>::alignment == 0);
0168 static_assert(members_ == 1);
0169 }
0170
0171 static int32_t computeDataSize(const SizesArray& sizes) {
0172 int32_t ret = 0;
0173 portablecollection::constexpr_for<0, members_>(
0174 [&sizes, &ret](auto i) { ret += Layout<i>::computeDataSize(sizes[i]); });
0175 return ret;
0176 }
0177
0178 PortableDeviceMultiCollection(const SizesArray& sizes, TDev const& device)
0179
0180 : buffer_{cms::alpakatools::make_device_buffer<std::byte[]>(device, computeDataSize(sizes))},
0181 impl_{buffer_->data(), sizes} {
0182 portablecollection::constexpr_for<0, members_>(
0183 [&](auto i) { assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout<i>::alignment == 0); });
0184 constexpr auto alignment = Layout<0>::alignment;
0185 portablecollection::constexpr_for<1, members_>(
0186 [&alignment](auto i) { static_assert(alignment == Layout<i>::alignment); });
0187 }
0188
0189 template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0190 PortableDeviceMultiCollection(const SizesArray& sizes, TQueue const& queue)
0191
0192 : buffer_{cms::alpakatools::make_device_buffer<std::byte[]>(queue, computeDataSize(sizes))},
0193 impl_{buffer_->data(), sizes} {
0194 portablecollection::constexpr_for<0, members_>(
0195 [&](auto i) { assert(reinterpret_cast<uintptr_t>(buffer_->data()) % Layout<i>::alignment == 0); });
0196 constexpr auto alignment = Layout<0>::alignment;
0197 portablecollection::constexpr_for<1, members_>(
0198 [&alignment](auto i) { static_assert(alignment == Layout<i>::alignment); });
0199 }
0200
0201
0202 PortableDeviceMultiCollection(PortableDeviceMultiCollection const&) = delete;
0203 PortableDeviceMultiCollection& operator=(PortableDeviceMultiCollection const&) = delete;
0204
0205
0206 PortableDeviceMultiCollection(PortableDeviceMultiCollection&&) = default;
0207 PortableDeviceMultiCollection& operator=(PortableDeviceMultiCollection&&) = default;
0208
0209
0210 ~PortableDeviceMultiCollection() = default;
0211
0212
0213 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0214 View<Idx>& view() {
0215 return get<Idx>().view_;
0216 }
0217
0218 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0219 ConstView<Idx> const& view() const {
0220 return get<Idx>().view_;
0221 }
0222
0223 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0224 ConstView<Idx> const& const_view() const {
0225 return get<Idx>().view_;
0226 }
0227
0228 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0229 View<Idx>& operator*() {
0230 return get<Idx>().view_;
0231 }
0232
0233 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0234 ConstView<Idx> const& operator*() const {
0235 return get<Idx>().view_;
0236 }
0237
0238 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0239 View<Idx>* operator->() {
0240 return &get<Idx>().view_;
0241 }
0242
0243 template <std::size_t Idx = 0, typename = std::enable_if_t<(members_ > Idx)>>
0244 ConstView<Idx> const* operator->() const {
0245 return &get<Idx>().view_;
0246 }
0247
0248
0249 template <typename T>
0250 typename T::View& view() {
0251 return get<T>().view_;
0252 }
0253
0254 template <typename T>
0255 typename T::ConstView const& view() const {
0256 return get<T>().view_;
0257 }
0258
0259 template <typename T>
0260 typename T::ConstView const& const_view() const {
0261 return get<T>().view_;
0262 }
0263
0264 template <typename T>
0265 typename T::View& operator*() {
0266 return get<T>().view_;
0267 }
0268
0269 template <typename T>
0270 typename T::ConstView const& operator*() const {
0271 return get<T>().view_;
0272 }
0273
0274 template <typename T>
0275 typename T::View* operator->() {
0276 return &get<T>().view_;
0277 }
0278
0279 template <typename T>
0280 typename T::ConstView const* operator->() const {
0281 return &get<T>().view_;
0282 }
0283
0284
0285 Buffer buffer() { return *buffer_; }
0286 ConstBuffer buffer() const { return *buffer_; }
0287 ConstBuffer const_buffer() const { return *buffer_; }
0288
0289
0290 template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0291 void zeroInitialise(TQueue&& queue) {
0292 alpaka::memset(std::forward<TQueue>(queue), *buffer_, 0x00);
0293 }
0294
0295
0296 SizesArray sizes() const {
0297 SizesArray ret;
0298 portablecollection::constexpr_for<0, members_>([&](auto i) { ret[i] = get<i>().layout_.metadata().size(); });
0299 return ret;
0300 }
0301
0302 private:
0303 std::optional<Buffer> buffer_;
0304 Implementation impl_;
0305 };
0306
0307 #endif