Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:15:40

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<Platform, 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<Platform, 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<Platform, std::remove_extent_t<T>, Idx>(
0102         host(), platform<Platform>(), Vec1D{std::extent_v<T>});
0103   }
0104 
0105   // potentially cached, pinned, scalar and 1-dimensional host buffers, associated to a work queue
0106   // the memory is pinned according to the device associated to the queue
0107 
0108   template <typename T, typename TQueue>
0109   std::enable_if_t<alpaka::isQueue<TQueue> and not std::is_array_v<T>, host_buffer<T>> make_host_buffer(
0110       TQueue const& queue) {
0111     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0112       return allocCachedBuf<T, Idx>(host(), queue, Scalar{});
0113     } else {
0114       using Platform = alpaka::Platform<alpaka::Dev<TQueue>>;
0115       return alpaka::allocMappedBuf<Platform, T, Idx>(host(), platform<Platform>(), Scalar{});
0116     }
0117   }
0118 
0119   template <typename T, typename TQueue>
0120   std::enable_if_t<alpaka::isQueue<TQueue> and cms::is_unbounded_array_v<T> and
0121                        not std::is_array_v<std::remove_extent_t<T>>,
0122                    host_buffer<T>>
0123   make_host_buffer(TQueue const& queue, Extent extent) {
0124     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0125       return allocCachedBuf<std::remove_extent_t<T>, Idx>(host(), queue, Vec1D{extent});
0126     } else {
0127       using Platform = alpaka::Platform<alpaka::Dev<TQueue>>;
0128       return alpaka::allocMappedBuf<Platform, std::remove_extent_t<T>, Idx>(
0129           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<Platform, 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   std::enable_if_t<cms::is_unbounded_array_v<T> and not std::is_array_v<std::remove_extent_t<T>>, host_view<T>>
0164   make_host_view(T& data, Extent extent) {
0165     return alpaka::ViewPlainPtr<DevHost, std::remove_extent_t<T>, Dim1D, Idx>(data, host(), Vec1D{extent});
0166   }
0167 
0168   template <typename T>
0169   std::enable_if_t<cms::is_bounded_array_v<T> and not std::is_array_v<std::remove_extent_t<T>>, host_view<T>>
0170   make_host_view(T& data) {
0171     return alpaka::ViewPlainPtr<DevHost, std::remove_extent_t<T>, Dim1D, Idx>(data, host(), Vec1D{std::extent_v<T>});
0172   }
0173 
0174   // scalar and 1-dimensional device buffers
0175 
0176   template <typename TDev, typename T, typename = std::enable_if_t<alpaka::isDevice<TDev>>>
0177   using device_buffer = typename detail::buffer_type<TDev, T>::type;
0178 
0179   template <typename TDev, typename T, typename = std::enable_if_t<alpaka::isDevice<TDev>>>
0180   using const_device_buffer = alpaka::ViewConst<device_buffer<TDev, T>>;
0181 
0182   // non-cached, scalar and 1-dimensional device buffers
0183 
0184   template <typename T, typename TDev>
0185   std::enable_if_t<alpaka::isDevice<TDev> and not std::is_array_v<T>, device_buffer<TDev, T>> make_device_buffer(
0186       TDev const& device) {
0187     return alpaka::allocBuf<T, Idx>(device, Scalar{});
0188   }
0189 
0190   template <typename T, typename TDev>
0191   std::enable_if_t<alpaka::isDevice<TDev> and cms::is_unbounded_array_v<T> and
0192                        not std::is_array_v<std::remove_extent_t<T>>,
0193                    device_buffer<TDev, T>>
0194   make_device_buffer(TDev const& device, Extent extent) {
0195     return alpaka::allocBuf<std::remove_extent_t<T>, Idx>(device, Vec1D{extent});
0196   }
0197 
0198   template <typename T, typename TDev>
0199   std::enable_if_t<alpaka::isDevice<TDev> and cms::is_bounded_array_v<T> and
0200                        not std::is_array_v<std::remove_extent_t<T>>,
0201                    device_buffer<TDev, T>>
0202   make_device_buffer(TDev const& device) {
0203     return alpaka::allocBuf<std::remove_extent_t<T>, Idx>(device, Vec1D{std::extent_v<T>});
0204   }
0205 
0206   // potentially-cached, scalar and 1-dimensional device buffers with queue-ordered semantic
0207 
0208   template <typename T, typename TQueue>
0209   std::enable_if_t<alpaka::isQueue<TQueue> and not std::is_array_v<T>, device_buffer<alpaka::Dev<TQueue>, T>>
0210   make_device_buffer(TQueue const& queue) {
0211     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0212       return allocCachedBuf<T, Idx>(alpaka::getDev(queue), queue, Scalar{});
0213     }
0214     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Asynchronous) {
0215       return alpaka::allocAsyncBuf<T, Idx>(queue, Scalar{});
0216     }
0217     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Synchronous) {
0218       return alpaka::allocBuf<T, Idx>(alpaka::getDev(queue), Scalar{});
0219     }
0220   }
0221 
0222   template <typename T, typename TQueue>
0223   std::enable_if_t<alpaka::isQueue<TQueue> and cms::is_unbounded_array_v<T> and
0224                        not std::is_array_v<std::remove_extent_t<T>>,
0225                    device_buffer<alpaka::Dev<TQueue>, T>>
0226   make_device_buffer(TQueue const& queue, Extent extent) {
0227     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0228       return allocCachedBuf<std::remove_extent_t<T>, Idx>(alpaka::getDev(queue), queue, Vec1D{extent});
0229     }
0230     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Asynchronous) {
0231       return alpaka::allocAsyncBuf<std::remove_extent_t<T>, Idx>(queue, Vec1D{extent});
0232     }
0233     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Synchronous) {
0234       return alpaka::allocBuf<std::remove_extent_t<T>, Idx>(alpaka::getDev(queue), Vec1D{extent});
0235     }
0236   }
0237 
0238   template <typename T, typename TQueue>
0239   std::enable_if_t<alpaka::isQueue<TQueue> and cms::is_bounded_array_v<T> and
0240                        not std::is_array_v<std::remove_extent_t<T>>,
0241                    device_buffer<alpaka::Dev<TQueue>, T>>
0242   make_device_buffer(TQueue const& queue) {
0243     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Caching) {
0244       return allocCachedBuf<std::remove_extent_t<T>, Idx>(alpaka::getDev(queue), queue, Vec1D{std::extent_v<T>});
0245     }
0246     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Asynchronous) {
0247       return alpaka::allocAsyncBuf<std::remove_extent_t<T>, Idx>(queue, Vec1D{std::extent_v<T>});
0248     }
0249     if constexpr (allocator_policy<alpaka::Dev<TQueue>> == AllocatorPolicy::Synchronous) {
0250       return alpaka::allocBuf<std::remove_extent_t<T>, Idx>(alpaka::getDev(queue), Vec1D{std::extent_v<T>});
0251     }
0252   }
0253 
0254   // scalar and 1-dimensional device views
0255 
0256   template <typename TDev, typename T, typename = std::enable_if_t<alpaka::isDevice<TDev>>>
0257   using device_view = typename detail::view_type<TDev, T>::type;
0258 
0259   template <typename T, typename TDev>
0260   std::enable_if_t<not std::is_array_v<T>, device_view<TDev, T>> make_device_view(TDev const& device, T& data) {
0261     return alpaka::ViewPlainPtr<TDev, T, Dim0D, Idx>(&data, device, Scalar{});
0262   }
0263 
0264   template <typename T, typename TDev>
0265   device_view<TDev, T[]> make_device_view(TDev const& device, T* data, Extent extent) {
0266     return alpaka::ViewPlainPtr<TDev, T, Dim1D, Idx>(data, device, Vec1D{extent});
0267   }
0268 
0269   template <typename T, typename TDev>
0270   std::enable_if_t<cms::is_unbounded_array_v<T> and not std::is_array_v<std::remove_extent_t<T>>, device_view<TDev, T>>
0271   make_device_view(TDev const& device, T& data, Extent extent) {
0272     return alpaka::ViewPlainPtr<TDev, std::remove_extent_t<T>, Dim1D, Idx>(data, device, Vec1D{extent});
0273   }
0274 
0275   template <typename T, typename TDev>
0276   std::enable_if_t<cms::is_bounded_array_v<T> and not std::is_array_v<std::remove_extent_t<T>>, device_view<TDev, T>>
0277   make_device_view(TDev const& device, T& data) {
0278     return alpaka::ViewPlainPtr<TDev, std::remove_extent_t<T>, Dim1D, Idx>(data, device, Vec1D{std::extent_v<T>});
0279   }
0280 
0281 }  // namespace cms::alpakatools
0282 
0283 #endif  // HeterogeneousCore_AlpakaInterface_interface_memory_h