cuDDL
Loading...
Searching...
No Matches
pinned_pool.cuh
Go to the documentation of this file.
1#pragma once
2
3#include <cuda_runtime.h>
4#include <cuda/devices>
5#include <cuda/memory_pool>
6
7#include <array>
8#include <cstdint>
9#include <limits>
10#include <mutex>
11#include <vector>
12
13#include <cuddl/cuda_error.hpp>
15
16namespace cuddl::detail {
17
19enum class pinned_placement : uint8_t {
26 host,
27};
28
39[[nodiscard]] inline cuda::pinned_memory_pool_ref
40device_pinned_pool(cuda::device_ref device, pinned_placement placement) {
41 static std::mutex mutex;
42 static std::vector<std::array<cudaMemPool_t, 2>> pools(cuda::devices.size());
43 std::lock_guard lock(mutex);
44 auto& pool = pools.at(static_cast<size_t>(device.get()))[static_cast<size_t>(placement)];
45 if (pool == nullptr) {
46 // Ablated, the pool behaves like CCCL's default pinned pool: mapped into every visible
47 // device and returning freed pages to the OS at every synchronisation. numa-pool
48 // separately puts device_node pages on any node.
49 bool const ablate = ablated("pinned-pool");
50 int node = -1;
51 CUDDL_CUDA_CALL(cudaDeviceGetAttribute(&node, cudaDevAttrHostNumaId, device.get()));
52 bool const numa =
53 !ablated("numa-pool") && placement == pinned_placement::device_node && node >= 0 &&
54 device.attribute(cuda::device_attributes::host_numa_memory_pools_supported) != 0;
55 cudaMemPoolProps properties{};
56 properties.allocType = cudaMemAllocationTypePinned;
57 properties.location = numa ? cudaMemLocation{cudaMemLocationTypeHostNuma, node}
58 : cudaMemLocation{cudaMemLocationTypeHost, 0};
59 cudaMemPool_t created = nullptr;
60 CUDDL_CUDA_CALL(cudaMemPoolCreate(&created, &properties));
61 cudaMemAccessDesc const access{
62 {cudaMemLocationTypeDevice, device.get()}, cudaMemAccessFlagsProtReadWrite
63 };
64 CUDDL_CUDA_CALL(cudaMemPoolSetAccess(created, &access, 1));
65 if (ablate) {
66 for (auto const& other : cuda::devices) {
67 cudaMemAccessDesc const shared{
68 {cudaMemLocationTypeDevice, other.get()}, cudaMemAccessFlagsProtReadWrite
69 };
70 CUDDL_CUDA_CALL(cudaMemPoolSetAccess(created, &shared, 1));
71 }
72 }
73 // Pinning is the expensive part of an allocation: with the default threshold of zero,
74 // every synchronisation returns freed pages to the OS and the next allocation pins them
75 // again, which cost sketch loaders more time than inflating their files.
76 auto keep = ablate ? uint64_t{0} : std::numeric_limits<uint64_t>::max();
77 CUDDL_CUDA_CALL(cudaMemPoolSetAttribute(created, cudaMemPoolAttrReleaseThreshold, &keep));
78 pool = created;
79 }
80 return cuda::pinned_memory_pool_ref(pool);
81}
82
89 public:
90 pinned_pool_trim(cuda::device_ref device, pinned_placement placement)
91 : pool_(device_pinned_pool(device, placement)) {}
95 (void)cudaMemPoolTrimTo(pool_.get(), 0);
96 }
97
98 private:
99 cuda::pinned_memory_pool_ref pool_;
100};
101
102} // namespace cuddl::detail
Returns the free pages of a device_pinned_pool to the OS when it leaves scope.
pinned_pool_trim & operator=(pinned_pool_trim const &)=delete
pinned_pool_trim(cuda::device_ref device, pinned_placement placement)
pinned_pool_trim(pinned_pool_trim const &)=delete
#define CUDDL_CUDA_CALL(err)
Checks a CUDA runtime call and throws std::runtime_error on failure.
pinned_placement
Where a device_pinned_pool takes its pages.
@ device_node
The device's host NUMA node, where the system supports NUMA pools: for buffers the device writes,...
@ host
Any node: for buffers host threads fill.
constexpr bool ablated(std::string_view) noexcept
Always false: this build compiles the ablation switches out.
Definition ablation.hpp:82
cuda::pinned_memory_pool_ref device_pinned_pool(cuda::device_ref device, pinned_placement placement)
A page-locked memory pool accessible from device only.