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
0019 using namespace alpaka_common;
0020
0021
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 }
0055
0056
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
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
0084
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
0107
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
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
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
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
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
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 }
0338
0339 #endif