Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-01-22 07:34:10

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