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