bounce_buffer.hpp
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #pragma once
6 
7 #include <stack>
8 #include <utility>
9 
10 #include <kvikio/defaults.hpp>
11 
12 namespace kvikio {
13 
22  public:
29  void* allocate(std::size_t size);
30 
37  void deallocate(void* buffer, std::size_t size);
38 };
39 
50  public:
57  void* allocate(std::size_t size);
58 
65  void deallocate(void* buffer, std::size_t size);
66 };
67 
79  public:
86  void* allocate(std::size_t size);
87 
94  void deallocate(void* buffer, std::size_t size);
95 };
96 
118 template <typename Allocator = CudaPinnedAllocator>
120  private:
121  mutable std::mutex _mutex{};
122  // Stack of free allocations (LIFO for cache locality)
123  std::stack<void*> _free_buffers{};
124  // The size of each allocation in `_free_buffers`
125  std::size_t _buffer_size{defaults::bounce_buffer_size()};
126  Allocator _allocator{};
127 
128  public:
137  class Buffer {
138  private:
139  BounceBufferPool* _pool;
140  void* _buffer;
141  std::size_t _size;
142 
143  public:
144  Buffer(BounceBufferPool<Allocator>* pool, void* buffer, std::size_t size);
145  Buffer(Buffer const&) = delete;
146  Buffer& operator=(Buffer const&) = delete;
147  Buffer(Buffer&& o) noexcept;
148  Buffer& operator=(Buffer&& o) noexcept;
149  ~Buffer() noexcept;
150  void* get() const noexcept;
151  void* get(std::ptrdiff_t offset) const noexcept;
152  std::size_t size() const noexcept;
153  };
154 
155  BounceBufferPool() = default;
156 
157  // Notice, we do not clear the allocations at destruction thus the allocations leaks
158  // at exit. We do this because `BounceBufferPool::instance()` stores the allocations in a
159  // static stack that are destructed below main, which is not allowed in CUDA:
160  // <https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#initialization>
161  ~BounceBufferPool() noexcept = default;
162 
163  private:
172  void _deallocate_buffers(std::stack<void*>& buffers, std::size_t buffer_size);
173 
184  [[nodiscard]] std::pair<std::stack<void*>, std::size_t> _detach_free_buffers();
185 
198  [[nodiscard]] std::pair<std::stack<void*>, std::size_t> _ensure_buffer_size();
199 
200  public:
210  [[nodiscard]] Buffer get();
211 
223  void put(void* buffer, std::size_t size) noexcept;
224 
233  std::size_t clear();
234 
242  std::size_t num_free_buffers() const;
243 
252  std::size_t buffer_size() const;
253 
261  KVIKIO_EXPORT static BounceBufferPool& instance();
262 
263  BounceBufferPool(BounceBufferPool const&) = delete;
264  BounceBufferPool& operator=(BounceBufferPool const&) = delete;
265  BounceBufferPool(BounceBufferPool&& o) = delete;
266  BounceBufferPool& operator=(BounceBufferPool&& o) = delete;
267 };
268 
275 
283 
291 } // namespace kvikio
RAII wrapper for a host bounce buffer allocation.
Thread-safe singleton pool for reusable bounce buffers.
void put(void *buffer, std::size_t size) noexcept
Return a buffer to the pool for reuse.
std::size_t num_free_buffers() const
Get the number of free buffers currently available in the pool.
std::size_t buffer_size() const
Get the current buffer size used by the pool.
std::size_t clear()
Free all retained allocations in the pool.
static KVIKIO_EXPORT BounceBufferPool & instance()
Get the singleton instance of the pool.
Buffer get()
Acquire a bounce buffer from the pool.
Allocator for page-aligned AND CUDA-registered pinned host memory.
void deallocate(void *buffer, std::size_t size)
Deallocate memory previously allocated by this allocator.
void * allocate(std::size_t size)
Allocate page-aligned CUDA-registered pinned host memory.
Allocator for CUDA pinned host memory.
void deallocate(void *buffer, std::size_t size)
Deallocate memory previously allocated by this allocator.
void * allocate(std::size_t size)
Allocate CUDA pinned host memory.
Allocator for page-aligned host memory.
void deallocate(void *buffer, std::size_t size)
Deallocate memory previously allocated by this allocator.
void * allocate(std::size_t size)
Allocate page-aligned host memory.
static std::size_t bounce_buffer_size()
Get the size of the bounce buffer used to stage data in host memory.
KvikIO namespace.
Definition: batch.hpp:16