File indexing completed on 2025-09-18 09:09:37
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <type_traits>
0010
0011 #ifndef CELER_DEVICE_COMPILE
0012 # include <vector>
0013
0014 # include "../DeviceVector.hh"
0015 #endif
0016
0017 #include "corecel/Assert.hh"
0018 #include "corecel/OpaqueId.hh"
0019 #include "corecel/Types.hh"
0020 #include "corecel/cont/Span.hh"
0021 #include "corecel/sys/Device.hh"
0022
0023 #include "DisabledStorage.hh"
0024 #include "TypeTraits.hh"
0025 #include "../Copier.hh"
0026 #include "../LdgIterator.hh"
0027 #include "../PinnedAllocator.hh"
0028
0029 namespace celeritas
0030 {
0031 namespace detail
0032 {
0033
0034 template<class T, Ownership W, MemSpace M, typename = void>
0035 struct CollectionTraits
0036 {
0037 using type = T;
0038 using const_type = T const;
0039 using reference_type = type&;
0040 using const_reference_type = const_type&;
0041 using SpanT = Span<type>;
0042 using SpanConstT = Span<const_type>;
0043 };
0044
0045
0046 template<class T, MemSpace M>
0047 struct CollectionTraits<T, Ownership::reference, M, void>
0048 {
0049 using type = T;
0050 using const_type = T;
0051 using reference_type = type&;
0052 using const_reference_type = const_type&;
0053 using SpanT = Span<type>;
0054 using SpanConstT = Span<const_type>;
0055 };
0056
0057
0058 template<class T, MemSpace M>
0059 struct CollectionTraits<T,
0060 Ownership::const_reference,
0061 M,
0062 std::enable_if_t<!is_ldg_supported_v<std::add_const_t<T>>>>
0063 {
0064 using type = T const;
0065 using const_type = T const;
0066 using reference_type = type&;
0067 using const_reference_type = const_type&;
0068 using SpanT = Span<type>;
0069 using SpanConstT = Span<const_type>;
0070 };
0071
0072
0073 template<class T, MemSpace M>
0074 struct CollectionTraits<T,
0075 Ownership::const_reference,
0076 M,
0077 std::enable_if_t<is_ldg_supported_v<std::add_const_t<T>>>>
0078 {
0079 using type = T const;
0080 using const_type = T const;
0081 using reference_type = type&;
0082 using const_reference_type = const_type&;
0083 using SpanT = Span<type>;
0084 using SpanConstT = Span<const_type>;
0085 };
0086
0087
0088 template<class T>
0089 struct CollectionTraits<T,
0090 Ownership::const_reference,
0091 MemSpace::device,
0092 std::enable_if_t<is_ldg_supported_v<std::add_const_t<T>>>>
0093 {
0094 using type = T const;
0095 using const_type = T const;
0096 using reference_type = type;
0097 using const_reference_type = const_type;
0098 using SpanT = LdgSpan<const_type>;
0099 using SpanConstT = LdgSpan<const_type>;
0100 };
0101
0102
0103
0104 template<class T, Ownership W, MemSpace M>
0105 struct CollectionStorage
0106 {
0107 using type = typename CollectionTraits<T, W, M>::SpanT;
0108 type data;
0109
0110 inline static constexpr Ownership ownership = W;
0111 inline static constexpr MemSpace memspace = M;
0112 };
0113
0114
0115
0116 template<class T>
0117 struct CollectionStorage<T, Ownership::value, MemSpace::host>
0118 {
0119 static_assert(!std::is_same<T, bool>::value,
0120 "bool is not compatible between vector and anything else");
0121 #ifdef CELER_DEVICE_COMPILE
0122
0123
0124 using type = DisabledStorage<T>;
0125 #else
0126 using type = std::vector<T>;
0127 #endif
0128 type data;
0129
0130 inline static constexpr Ownership ownership = Ownership::value;
0131 inline static constexpr MemSpace memspace = MemSpace::host;
0132 };
0133
0134
0135 template<class T>
0136 struct CollectionStorage<T, Ownership::value, MemSpace::device>
0137 {
0138 #ifdef CELER_DEVICE_COMPILE
0139
0140
0141 using type = DisabledStorage<T>;
0142 #else
0143 using type = DeviceVector<T>;
0144 #endif
0145 type data;
0146
0147 inline static constexpr Ownership ownership = Ownership::value;
0148 inline static constexpr MemSpace memspace = MemSpace::device;
0149 };
0150
0151
0152 template<class T>
0153 struct CollectionStorage<T, Ownership::value, MemSpace::mapped>
0154 {
0155 static_assert(!std::is_same<T, bool>::value,
0156 "bool is not compatible between vector and anything else");
0157 #ifdef CELER_DEVICE_COMPILE
0158
0159
0160 using type = DisabledStorage<T>;
0161 #else
0162 using type = std::vector<T, PinnedAllocator<T>>;
0163 #endif
0164 type data;
0165
0166 inline static constexpr Ownership ownership = Ownership::value;
0167 inline static constexpr MemSpace memspace = MemSpace::mapped;
0168 };
0169
0170
0171
0172 template<Ownership W>
0173 struct CollectionStorageValidator
0174 {
0175 template<class Size, class OtherSize>
0176 void operator()(Size, OtherSize)
0177 {
0178
0179 }
0180 };
0181
0182 template<>
0183 struct CollectionStorageValidator<Ownership::value>
0184 {
0185 template<class Size, class OtherSize>
0186 void operator()(Size dst, OtherSize src)
0187 {
0188 CELER_VALIDATE(dst == src,
0189 << "collection is too large (" << sizeof(Size)
0190 << "-byte int cannot hold " << src << " elements)");
0191 }
0192 };
0193
0194
0195
0196
0197
0198 template<class S, class T, Ownership DW, MemSpace DM>
0199 void copy_collection(S& src, CollectionStorage<T, DW, DM>* dst)
0200 {
0201 constexpr MemSpace SM = std::remove_const_t<S>::memspace;
0202 using DstStorageT = typename CollectionStorage<T, DW, DM>::type;
0203
0204 auto* data = src.data.data();
0205 size_type size = src.data.size();
0206
0207 if constexpr (DW == Ownership::value && DM == MemSpace::mapped)
0208 {
0209 CELER_VALIDATE(celeritas::device().can_map_host_memory(),
0210 << "device " << celeritas::device().device_id()
0211 << " doesn't support unified addressing");
0212 }
0213
0214 if constexpr (DW == Ownership::value && DM == SM)
0215 {
0216
0217 dst->data.assign(data, data + size);
0218 }
0219 else if constexpr (DM == SM)
0220 {
0221
0222 constexpr Ownership SW = std::remove_const_t<S>::ownership;
0223
0224 static_assert(
0225 !(SW == Ownership::const_reference && DW == Ownership::reference),
0226 "cannot assign from const reference to reference");
0227
0228 dst->data = DstStorageT{data, size};
0229 }
0230 else
0231 {
0232 if constexpr (DW == Ownership::value)
0233 {
0234
0235 dst->data = DstStorageT(size);
0236 }
0237
0238 CELER_VALIDATE(dst->data.size() == size,
0239 << "collection assignment from " << to_cstring(SM)
0240 << " to " << to_cstring(DM)
0241 << " failed: cannot copy from source size " << size
0242 << " to destination size " << dst->data.size());
0243
0244
0245 Copier<T, DM> copy_to_dst{{dst->data.data(), dst->data.size()}};
0246 copy_to_dst(SM, {data, size});
0247 }
0248 }
0249
0250
0251 }
0252 }