File indexing completed on 2024-07-02 00:53:48
0001 #ifndef HeterogeneousCore_AlpakaInterface_interface_getDeviceCachingAllocator_h
0002 #define HeterogeneousCore_AlpakaInterface_interface_getDeviceCachingAllocator_h
0003
0004 #include <cassert>
0005 #include <memory>
0006
0007 #include <alpaka/alpaka.hpp>
0008
0009 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0010 #include "HeterogeneousCore/AlpakaInterface/interface/AllocatorConfig.h"
0011 #include "HeterogeneousCore/AlpakaInterface/interface/CachingAllocator.h"
0012 #include "HeterogeneousCore/AlpakaInterface/interface/devices.h"
0013
0014 namespace cms::alpakatools {
0015
0016 namespace detail {
0017
0018 template <typename TDev,
0019 typename TQueue,
0020 typename = std::enable_if_t<alpaka::isDevice<TDev> and alpaka::isQueue<TQueue>>>
0021 auto allocate_device_allocators(AllocatorConfig const& config, bool debug) {
0022 using Allocator = CachingAllocator<TDev, TQueue>;
0023 auto const& devices = cms::alpakatools::devices<alpaka::Platform<TDev>>();
0024 ssize_t const size = devices.size();
0025
0026
0027 auto ptr = std::allocator<Allocator>().allocate(size);
0028
0029
0030 ptrdiff_t index = 0;
0031 try {
0032 for (; index < size; ++index) {
0033 #if __cplusplus >= 202002L
0034 std::construct_at(
0035 #else
0036 std::allocator<Allocator>().construct(
0037 #endif
0038 ptr + index,
0039 devices[index],
0040 config,
0041 true,
0042 debug);
0043 }
0044 } catch (...) {
0045 --index;
0046
0047 while (index >= 0) {
0048 std::destroy_at(ptr + index);
0049 --index;
0050 }
0051
0052 std::allocator<Allocator>().deallocate(ptr, size);
0053
0054 throw;
0055 }
0056
0057
0058 auto deleter = [size](Allocator* allocators) {
0059 for (size_t i = size; i > 0; --i) {
0060 std::destroy_at(allocators + i - 1);
0061 }
0062 std::allocator<Allocator>().deallocate(allocators, size);
0063 };
0064
0065 return std::unique_ptr<Allocator[], decltype(deleter)>(ptr, deleter);
0066 }
0067
0068 }
0069
0070 template <typename TDev,
0071 typename TQueue,
0072 typename = std::enable_if_t<alpaka::isDevice<TDev> and alpaka::isQueue<TQueue>>>
0073 inline CachingAllocator<TDev, TQueue>& getDeviceCachingAllocator(TDev const& device,
0074 AllocatorConfig const& config = AllocatorConfig{},
0075 bool debug = false) {
0076
0077 CMS_THREAD_SAFE static auto allocators = detail::allocate_device_allocators<TDev, TQueue>(config, debug);
0078
0079 size_t const index = alpaka::getNativeHandle(device);
0080 assert(index < cms::alpakatools::devices<alpaka::Platform<TDev>>().size());
0081
0082
0083 return allocators[index];
0084 }
0085
0086 }
0087
0088 #endif