Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:46

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2021-2024 UT-Battelle, LLC, and other Celeritas developers.
0003 // See the top-level COPYRIGHT file for details.
0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0005 //---------------------------------------------------------------------------//
0006 //! \file corecel/data/detail/CollectionImpl.hh
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 //! Memspace-dependent storage for a collection
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 //! Storage implementation for managed host data
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     // Use "not implemented" but __host__ __device__ decorated functions when
0124     // compiling in CUDA
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 //! Storage implementation for managed device data
0136 template<class T>
0137 struct CollectionStorage<T, Ownership::value, MemSpace::device>
0138 {
0139 #ifdef CELER_DEVICE_COMPILE
0140     // Use "not implemented" but __host__ __device__ decorated functions when
0141     // compiling in CUDA
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 //! Storage implementation for mapped host/device data
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     // Use "not implemented" but __host__ __device__ decorated functions when
0160     // compiling in CUDA
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 //! Check that sizes are acceptable when creating references from values
0173 template<Ownership W>
0174 struct CollectionStorageValidator
0175 {
0176     template<class Size, class OtherSize>
0177     void operator()(Size, OtherSize)
0178     {
0179         /* No validation needed */
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  * Copy assign a collection via its storage.
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         // Allocate and copy at the same time: destination "owns" the memory
0218         dst->data.assign(data, data + size);
0219     }
0220     else if constexpr (DM == SM)
0221     {
0222         // Copy pointers in same memspace, prohibiting const violation
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             // Allocate destination
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         // Copy across memory boundary
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 }  // namespace detail
0253 }  // namespace celeritas