Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-15 23:01:15

0001 #ifndef HeterogeneousCore_AlpakaInterface_interface_memory_h
0002 #define HeterogeneousCore_AlpakaInterface_interface_memory_h
0003 
0004 #include <type_traits>
0005 
0006 #include <span>
0007 
0008 #include <alpaka/alpaka.hpp>
0009 
0010 #include "HeterogeneousCore/AlpakaInterface/interface/AllocatorPolicy.h"
0011 #include "HeterogeneousCore/AlpakaInterface/interface/CachedBufAlloc.h"
0012 #include "HeterogeneousCore/AlpakaInterface/interface/config.h"
0013 #include "HeterogeneousCore/AlpakaInterface/interface/devices.h"
0014 #include "HeterogeneousCore/AlpakaInterface/interface/traits.h"
0015 
0016 namespace cms::alpakatools {
0017 
0018   // for Extent, Dim1D, Idx
0019   using namespace alpaka_common;
0020 
0021   // type deduction helpers
0022   namespace detail {
0023 
0024     template <typename TDev, typename T, typename = std::enable_if_t<alpaka::isDevice<TDev>>>
0025     struct buffer_type {
0026       using type = alpaka::Buf<TDev, T, Dim0D, Idx>;
0027     };
0028 
0029     template <typename TDev, typename T>
0030     struct buffer_type<TDev, T[]> {
0031       using type = alpaka::Buf<TDev, T, Dim1D, Idx>;
0032     };
0033 
0034     template <typename TDev, typename T, int N>
0035     struct buffer_type<TDev, T[N]> {
0036       using type = alpaka::Buf<TDev, T, Dim1D, Idx>;
0037     };
0038 
0039     template <typename TDev, typename T, typename = std::enable_if_t<alpaka::isDevice<TDev>>>
0040     struct view_type {
0041       using type = alpaka::ViewPlainPtr<TDev, T, Dim0D, Idx>;
0042     };
0043 
0044     template <typename TDev, typename T>
0045     struct view_type<TDev, T[]> {
0046       using type = alpaka::ViewPlainPtr<TDev, T, Dim1D, Idx>;
0047     };
0048 
0049     template <typename TDev, typename T, int N>
0050     struct view_type<TDev, T[N]> {
0051       using type = alpaka::ViewPlainPtr<TDev, T, Dim1D, Idx>;
0052     };
0053 
0054   }  // namespace detail
0055 
0056   // scalar and 1-dimensional host buffers
0057 
0058   template <typename T>
0059   using host_buffer = typename detail::buffer_type<DevHost, T>::type;
0060 
0061   template <typename T>
0062   using const_host_buffer = alpaka::ViewConst<host_buffer<T>>;
0063 
0064   // non-cached, non-pinned, scalar and 1-dimensional host buffers
0065 
0066   template <typename T>
0067   std::enable_if_t<not std::is_array_v<T>, host_buffer<T>> make_host_buffer() {
0068     return alpaka::allocBuf<T, Idx>(host(), Scalar{});
0069   }
0070 
0071   template <typename T>
0072   std::enable_if_t<cms::is_unbounded_array_v<T> and not std::is_array_v<std::remove_extent_t<T>>, host_buffer<T>>
0073   make_host_buffer(Extent extent) {
0074     return alpaka::allocBuf<std::remove_extent_t<T>, Idx>(host(), Vec1D{extent});
0075   }
0076 
0077   template <typename T>
0078   std::enable_if_t<cms::is_bounded_array_v<T> and not std::is_array_v<std::remove_extent_t<T>>, host_buffer<T>>
0079   make_host_buffer() {
0080     return alpaka::allocBuf<std::remove_extent_t<T>, Idx>(host(), Vec1D{std::extent_v<T>});
0081   }
0082 
0083   // non-cached, pinned, scalar and 1-dimensional host buffers
0084   // the memory is pinned according to the device associated to the platform
0085 
0086   template <typename T, typename TPlatform>
0087   std::enable_if_t<not std::is_array_v<T>, host_buffer<T>> make_host_buffer() {
0088     using Platform = TPlatform;
0089     return alpaka::allocMappedBuf<T, Idx>(host(), platform<Platform>(), Scalar{});
0090   }
0091 
0092   template <typename T, typename TPlatform>
0093   std::enable_if_t<cms::is_unbounded_array_v<T> and not std::is_array_v<std::remove_extent_t<T>>, host_buffer<T>>
0094   make_host_buffer(Extent extent) {
0095     using Platform = TPlatform;
0096     return alpaka::allocMappedBuf<std::remove_extent_t<T>, Idx>(host(), platform<Platform>(), Vec1D{extent});
0097   }
0098 
0099   template <typename T, typename TPlatform>
0100   std::enable_if_t<cms::is_bounded_array_v<T> and not std::is_array_v<std::remove_extent_t<T>>, host_buffer<T>>
0101   make_host_buffer() {
0102     using Platform = TPlatform;
0103     return alpaka::allocMappedBuf<std::remove_extent_t<T>, Idx>(host(), platform<Platform>(), Vec1D{std::extent_v<T>});
0104   }
0105 
0106   // potentially cached, pinned, scalar and 1-dimensional host buffers, associated to a work queue
0107   // the memory is pinned according to the device associated to the queue
0108 
0109   template <typename T, typename TQueue>
0110   std::enable_if_t<alpaka::isQueue<TQueue> and not std::is_array_v<T>, host_buffer<T>> make_host_buffer(
0111       TQueue const& queue) {
0112     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0113       return allocCachedBuf<T, Idx>(host(), queue, Scalar{});
0114     } else {
0115       using Platform = alpaka::Platform<alpaka::Dev<TQueue>>;
0116       return alpaka::allocMappedBuf<T, Idx>(host(), platform<Platform>(), Scalar{});
0117     }
0118   }
0119 
0120   template <typename T, typename TQueue>
0121   std::enable_if_t<alpaka::isQueue<TQueue> and cms::is_unbounded_array_v<T> and
0122                        not std::is_array_v<std::remove_extent_t<T>>,
0123                    host_buffer<T>>
0124   make_host_buffer(TQueue const& queue, Extent extent) {
0125     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0126       return allocCachedBuf<std::remove_extent_t<T>, Idx>(host(), queue, Vec1D{extent});
0127     } else {
0128       using Platform = alpaka::Platform<alpaka::Dev<TQueue>>;
0129       return alpaka::allocMappedBuf<std::remove_extent_t<T>, Idx>(host(), platform<Platform>(), Vec1D{extent});
0130     }
0131   }
0132 
0133   template <typename T, typename TQueue>
0134   std::enable_if_t<alpaka::isQueue<TQueue> and cms::is_bounded_array_v<T> and
0135                        not std::is_array_v<std::remove_extent_t<T>>,
0136                    host_buffer<T>>
0137   make_host_buffer(TQueue const& queue) {
0138     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0139       return allocCachedBuf<std::remove_extent_t<T>, Idx>(host(), queue, Vec1D{std::extent_v<T>});
0140     } else {
0141       using Platform = alpaka::Platform<alpaka::Dev<TQueue>>;
0142       return alpaka::allocMappedBuf<std::remove_extent_t<T>, Idx>(
0143           host(), platform<Platform>(), Vec1D{std::extent_v<T>});
0144     }
0145   }
0146 
0147   // scalar and 1-dimensional host views
0148 
0149   template <typename T>
0150   using host_view = typename detail::view_type<DevHost, T>::type;
0151 
0152   template <typename T>
0153   std::enable_if_t<not std::is_array_v<T>, host_view<T>> make_host_view(T& data) {
0154     return alpaka::ViewPlainPtr<DevHost, T, Dim0D, Idx>(&data, host(), Scalar{});
0155   }
0156 
0157   template <typename T>
0158   host_view<T[]> make_host_view(T* data, Extent extent) {
0159     return alpaka::ViewPlainPtr<DevHost, T, Dim1D, Idx>(data, host(), Vec1D{extent});
0160   }
0161 
0162   template <typename T>
0163   host_view<T[]> make_host_view(std::span<T> span) {
0164     return alpaka::ViewPlainPtr<DevHost, T, Dim1D, Idx>(span.data(), host(), Vec1D{span.size()});
0165   }
0166 
0167   template <typename T>
0168   std::enable_if_t<cms::is_unbounded_array_v<T> and not std::is_array_v<std::remove_extent_t<T>>, host_view<T>>
0169   make_host_view(T& data, Extent extent) {
0170     return alpaka::ViewPlainPtr<DevHost, std::remove_extent_t<T>, Dim1D, Idx>(data, host(), Vec1D{extent});
0171   }
0172 
0173   template <typename T>
0174   std::enable_if_t<cms::is_bounded_array_v<T> and not std::is_array_v<std::remove_extent_t<T>>, host_view<T>>
0175   make_host_view(T& data) {
0176     return alpaka::ViewPlainPtr<DevHost, std::remove_extent_t<T>, Dim1D, Idx>(data, host(), Vec1D{std::extent_v<T>});
0177   }
0178 
0179   // scalar and 1-dimensional device buffers
0180 
0181   template <typename TDev, typename T, typename = std::enable_if_t<alpaka::isDevice<TDev>>>
0182   using device_buffer = typename detail::buffer_type<TDev, T>::type;
0183 
0184   template <typename TDev, typename T, typename = std::enable_if_t<alpaka::isDevice<TDev>>>
0185   using const_device_buffer = alpaka::ViewConst<device_buffer<TDev, T>>;
0186 
0187   // non-cached, scalar and 1-dimensional device buffers
0188 
0189   template <typename T, typename TDev>
0190   std::enable_if_t<alpaka::isDevice<TDev> and not std::is_array_v<T>, device_buffer<TDev, T>> make_device_buffer(
0191       TDev const& device) {
0192     return alpaka::allocBuf<T, Idx>(device, Scalar{});
0193   }
0194 
0195   template <typename T, typename TDev>
0196   std::enable_if_t<alpaka::isDevice<TDev> and cms::is_unbounded_array_v<T> and
0197                        not std::is_array_v<std::remove_extent_t<T>>,
0198                    device_buffer<TDev, T>>
0199   make_device_buffer(TDev const& device, Extent extent) {
0200     return alpaka::allocBuf<std::remove_extent_t<T>, Idx>(device, Vec1D{extent});
0201   }
0202 
0203   template <typename T, typename TDev>
0204   std::enable_if_t<alpaka::isDevice<TDev> and cms::is_bounded_array_v<T> and
0205                        not std::is_array_v<std::remove_extent_t<T>>,
0206                    device_buffer<TDev, T>>
0207   make_device_buffer(TDev const& device) {
0208     return alpaka::allocBuf<std::remove_extent_t<T>, Idx>(device, Vec1D{std::extent_v<T>});
0209   }
0210 
0211   // potentially-cached, scalar and 1-dimensional device buffers with queue-ordered semantic
0212 
0213   template <typename T, typename TQueue>
0214   std::enable_if_t<alpaka::isQueue<TQueue> and not std::is_array_v<T>, device_buffer<alpaka::Dev<TQueue>, T>>
0215   make_device_buffer(TQueue const& queue) {
0216     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0217       return allocCachedBuf<T, Idx>(alpaka::getDev(queue), queue, Scalar{});
0218     }
0219     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Asynchronous) {
0220       return alpaka::allocAsyncBuf<T, Idx>(queue, Scalar{});
0221     }
0222     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Synchronous) {
0223       return alpaka::allocBuf<T, Idx>(alpaka::getDev(queue), Scalar{});
0224     }
0225   }
0226 
0227   template <typename T, typename TQueue>
0228   std::enable_if_t<alpaka::isQueue<TQueue> and cms::is_unbounded_array_v<T> and
0229                        not std::is_array_v<std::remove_extent_t<T>>,
0230                    device_buffer<alpaka::Dev<TQueue>, T>>
0231   make_device_buffer(TQueue const& queue, Extent extent) {
0232     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0233       return allocCachedBuf<std::remove_extent_t<T>, Idx>(alpaka::getDev(queue), queue, Vec1D{extent});
0234     }
0235     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Asynchronous) {
0236       return alpaka::allocAsyncBuf<std::remove_extent_t<T>, Idx>(queue, Vec1D{extent});
0237     }
0238     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Synchronous) {
0239       return alpaka::allocBuf<std::remove_extent_t<T>, Idx>(alpaka::getDev(queue), Vec1D{extent});
0240     }
0241   }
0242 
0243   template <typename T, typename TQueue>
0244   std::enable_if_t<alpaka::isQueue<TQueue> and cms::is_bounded_array_v<T> and
0245                        not std::is_array_v<std::remove_extent_t<T>>,
0246                    device_buffer<alpaka::Dev<TQueue>, T>>
0247   make_device_buffer(TQueue const& queue) {
0248     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0249       return allocCachedBuf<std::remove_extent_t<T>, Idx>(alpaka::getDev(queue), queue, Vec1D{std::extent_v<T>});
0250     }
0251     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Asynchronous) {
0252       return alpaka::allocAsyncBuf<std::remove_extent_t<T>, Idx>(queue, Vec1D{std::extent_v<T>});
0253     }
0254     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Synchronous) {
0255       return alpaka::allocBuf<std::remove_extent_t<T>, Idx>(alpaka::getDev(queue), Vec1D{std::extent_v<T>});
0256     }
0257   }
0258 
0259   // scalar and 1-dimensional device views
0260 
0261   template <typename TDev, typename T, typename = std::enable_if_t<alpaka::isDevice<TDev>>>
0262   using device_view = typename detail::view_type<TDev, T>::type;
0263 
0264   template <typename T, typename TDev>
0265   std::enable_if_t<alpaka::isDevice<TDev> and not std::is_array_v<T>, device_view<TDev, T>> make_device_view(
0266       TDev const& device, T& data) {
0267     return alpaka::ViewPlainPtr<TDev, T, Dim0D, Idx>(&data, device, Scalar{});
0268   }
0269 
0270   template <typename T, typename TDev>
0271   std::enable_if_t<alpaka::isDevice<TDev>, device_view<TDev, T[]>> make_device_view(TDev const& device,
0272                                                                                     T* data,
0273                                                                                     Extent extent) {
0274     return alpaka::ViewPlainPtr<TDev, T, Dim1D, Idx>(data, device, Vec1D{extent});
0275   }
0276 
0277   template <typename T, typename TDev>
0278   std::enable_if_t<alpaka::isDevice<TDev>, device_view<TDev, T[]>> make_device_view(TDev const& device,
0279                                                                                     std::span<T> span) {
0280     return alpaka::ViewPlainPtr<TDev, T, Dim1D, Idx>(span.data(), device, Vec1D{span.size()});
0281   }
0282 
0283   template <typename T, typename TDev>
0284   std::enable_if_t<alpaka::isDevice<TDev> and cms::is_unbounded_array_v<T> and
0285                        not std::is_array_v<std::remove_extent_t<T>>,
0286                    device_view<TDev, T>>
0287   make_device_view(TDev const& device, T& data, Extent extent) {
0288     return alpaka::ViewPlainPtr<TDev, std::remove_extent_t<T>, Dim1D, Idx>(data, device, Vec1D{extent});
0289   }
0290 
0291   template <typename T, typename TDev>
0292   std::enable_if_t<alpaka::isDevice<TDev> and cms::is_bounded_array_v<T> and
0293                        not std::is_array_v<std::remove_extent_t<T>>,
0294                    device_view<TDev, T>>
0295   make_device_view(TDev const& device, T& data) {
0296     return alpaka::ViewPlainPtr<TDev, std::remove_extent_t<T>, Dim1D, Idx>(data, device, Vec1D{std::extent_v<T>});
0297   }
0298 
0299   template <typename T, typename TQueue>
0300   std::enable_if_t<alpaka::isQueue<TQueue> and not std::is_array_v<T>, device_view<alpaka::Dev<TQueue>, T>>
0301   make_device_view(TQueue const& queue, T& data) {
0302     return alpaka::ViewPlainPtr<alpaka::Dev<TQueue>, T, Dim0D, Idx>(&data, alpaka::getDev(queue), Scalar{});
0303   }
0304 
0305   template <typename T, typename TQueue>
0306   std::enable_if_t<alpaka::isQueue<TQueue>, device_view<alpaka::Dev<TQueue>, T[]>> make_device_view(TQueue const& queue,
0307                                                                                                     T* data,
0308                                                                                                     Extent extent) {
0309     return alpaka::ViewPlainPtr<alpaka::Dev<TQueue>, T, Dim1D, Idx>(data, alpaka::getDev(queue), Vec1D{extent});
0310   }
0311 
0312   template <typename T, typename TQueue>
0313   std::enable_if_t<alpaka::isQueue<TQueue>, device_view<alpaka::Dev<TQueue>, T[]>> make_device_view(TQueue const& queue,
0314                                                                                                     std::span<T> span) {
0315     return alpaka::ViewPlainPtr<alpaka::Dev<TQueue>, T, Dim1D, Idx>(
0316         span.data(), alpaka::getDev(queue), Vec1D{span.size()});
0317   }
0318 
0319   template <typename T, typename TQueue>
0320   std::enable_if_t<alpaka::isQueue<TQueue> and cms::is_unbounded_array_v<T> and
0321                        not std::is_array_v<std::remove_extent_t<T>>,
0322                    device_view<alpaka::Dev<TQueue>, T>>
0323   make_device_view(TQueue const& queue, T& data, Extent extent) {
0324     return alpaka::ViewPlainPtr<alpaka::Dev<TQueue>, std::remove_extent_t<T>, Dim1D, Idx>(
0325         data, alpaka::getDev(queue), Vec1D{extent});
0326   }
0327 
0328   template <typename T, typename TQueue>
0329   std::enable_if_t<alpaka::isQueue<TQueue> and cms::is_bounded_array_v<T> and
0330                        not std::is_array_v<std::remove_extent_t<T>>,
0331                    device_view<alpaka::Dev<TQueue>, T>>
0332   make_device_view(TQueue const& queue, T& data) {
0333     return alpaka::ViewPlainPtr<alpaka::Dev<TQueue>, std::remove_extent_t<T>, Dim1D, Idx>(
0334         data, alpaka::getDev(queue), Vec1D{std::extent_v<T>});
0335   }
0336 
0337 }  // namespace cms::alpakatools
0338 
0339 #endif  // HeterogeneousCore_AlpakaInterface_interface_memory_h