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