12#include <cuda_runtime_api.h>
22#include <unordered_map>
33 requires std::is_trivially_copyable_v<T>
38class AllocationReclaimer;
40template <
typename T>
class CudaAllocation;
53 [[nodiscard]]
int device() const noexcept {
return device_; }
77 [[nodiscard]]
explicit operator bool() const noexcept {
return static_cast<bool>(state_); }
80 [[nodiscard]]
int device() const noexcept;
96 explicit
Stream(
std::shared_ptr<State> state) noexcept;
98 std::shared_ptr<State> state_;
114 [[nodiscard]]
explicit operator bool() const noexcept {
return static_cast<bool>(state_); }
117 [[nodiscard]]
int device() const noexcept;
120 [[nodiscard]]
bool ready() const;
130 std::shared_ptr<State> state_;
134 friend class detail::AllocationReclaimer;
143 using notify_type = void (*)(StreamWaiter&,
Stream)
noexcept;
145 explicit StreamWaiter(notify_type notify) noexcept : notify_(notify) {
CHECK(notify_ !=
nullptr); }
146 StreamWaiter(StreamWaiter
const&) =
delete;
147 StreamWaiter& operator=(StreamWaiter
const&) =
delete;
150 void notify(
Stream stream)
noexcept { notify_(*
this, std::move(stream)); }
153 StreamWaiter* next_ =
nullptr;
154 bool queued_ =
false;
156 friend class ::uni20::cuda::StreamPool;
170 unsigned int stream_flags = cudaStreamNonBlocking;
180 [[nodiscard]] std::optional<Stream> try_acquire();
185 [[nodiscard]]
Stream acquire();
188 [[nodiscard]] std::optional<Stream> acquire_or_enqueue(detail::StreamWaiter& waiter)
noexcept;
191 [[nodiscard]]
int device() const noexcept;
194 [[nodiscard]]
std::
size_t size() const noexcept;
197 [[nodiscard]]
std::
size_t idle_stream_count() const noexcept;
200 [[nodiscard]]
std::
size_t leased_stream_count() const noexcept;
203 [[nodiscard]]
std::
size_t pending_stream_count() const noexcept;
229 unsigned int stream_flags = cudaStreamNonBlocking;
252 template <
class Resource,
class... Args> [[nodiscard]] Resource&
provider_resource(Args&&... args)
254 std::lock_guard lock(provider_resources_mutex_);
255 auto const key = std::type_index(
typeid(Resource));
256 auto found = provider_resources_.find(key);
257 if (found != provider_resources_.end())
259 return static_cast<ProviderResourceModel<Resource>&
>(*found->second).
value;
262 auto resource = std::make_unique<ProviderResourceModel<Resource>>(std::forward<Args>(args)...);
263 Resource& result = resource->value;
264 provider_resources_.emplace(key, std::move(resource));
271 return live_allocation_count_.load(std::memory_order_acquire);
275 struct ProviderResourceBase
277 virtual ~ProviderResourceBase() =
default;
280 template <
class Resource>
struct ProviderResourceModel final : ProviderResourceBase
282 template <
class... Args>
explicit ProviderResourceModel(Args&&... args) :
value(
std::forward<Args>(args)...) {}
287 void register_allocation() noexcept { live_allocation_count_.fetch_add(1, std::memory_order_relaxed); }
288 void unregister_allocation() noexcept;
289 void defer_allocation_release_after(
std::
span<Completion const> completions) noexcept;
290 void release_allocation(
void* allocation,
bool blocking) noexcept;
291 void destroy_provider_resources() noexcept;
295 std::unique_ptr<detail::AllocationReclaimer> allocation_reclaimer_;
296 std::mutex provider_resources_mutex_;
297 std::unordered_map<
std::type_index,
std::unique_ptr<ProviderResourceBase>> provider_resources_;
298 std::atomic<
std::
size_t> live_allocation_count_ = 0;
300 template <typename T>
301 requires
std::is_trivially_copyable_v<T>
303 template <typename> friend class detail::CudaAllocation;
310 std::vector<int> device_ordinals{};
312 std::optional<int> default_device{};
314 std::size_t streams_per_device = 8;
316 unsigned int stream_flags = cudaStreamNonBlocking;
333 [[nodiscard]]
bool has_device(
int device) const noexcept;
342 [[nodiscard]]
std::optional<
int> default_device() const noexcept {
return default_device_; }
345 struct construction_key
348 explicit Runtime(RuntimeConfig config, construction_key);
350 std::vector<std::unique_ptr<DeviceResources>> device_resources_;
351 std::optional<int> default_device_;
353 friend Runtime initialize(RuntimeConfig);
359[[nodiscard]] Runtime
initialize(RuntimeConfig config = {});
365[[nodiscard]] Runtime&
runtime();
Definition runtime.cpp:89
Shared completion token for one submitted CUDA operation.
Definition runtime.hpp:104
Move-only logical CUDA buffer and completion state.
Definition buffer.hpp:222
Mutable stream and provider resources associated with one CUDA device.
Definition runtime.hpp:222
std::size_t live_allocation_count() const noexcept
Return the number of live CUDA allocations borrowing these resources.
Definition runtime.hpp:269
DeviceResources & operator=(DeviceResources const &)=delete
DeviceResources(DeviceResources const &)=delete
StreamPool const & streams() const noexcept
Definition runtime.hpp:245
DeviceResources(DeviceResources &&)=delete
Resource & provider_resource(Args &&... args)
Return the resource-owned instance of one provider resource type.
Definition runtime.hpp:252
DeviceResources & operator=(DeviceResources &&)=delete
StreamPool & streams() noexcept
Return the device's actually-idle stream pool.
Definition runtime.hpp:244
Validated CUDA device identity with cached immutable capabilities.
Definition device.hpp:105
Scoped owner of the process-wide CUDA resource installation.
Definition runtime.hpp:324
Runtime(Runtime &&)=delete
Runtime & operator=(Runtime const &)=delete
Runtime & operator=(Runtime &&)=delete
Runtime(Runtime const &)=delete
Temporarily select one CUDA device and restore the previous device on destruction.
Definition runtime.hpp:44
ScopedDevice & operator=(ScopedDevice const &)=delete
int device() const noexcept
Return the selected device ordinal.
Definition runtime.hpp:53
~ScopedDevice()
Definition runtime.cpp:81
ScopedDevice(ScopedDevice const &)=delete
Definition runtime.cpp:333
Device-local pool whose streams become available only after their queued work completes.
Definition runtime.hpp:163
StreamPool(StreamPool const &)=delete
StreamPool & operator=(StreamPool const &)=delete
Definition runtime.cpp:260
Reference-counted lease of one CUDA stream-pool slot.
Definition runtime.hpp:65
void synchronize() const
Wait on all work currently queued in this stream.
Definition runtime.cpp:292
cudaStream_t native_handle() const noexcept
Return the CUDA runtime stream handle.
Definition runtime.cpp:286
Completion record_completion() const
Record and return an immutable completion for the current stream tail.
Definition runtime.cpp:298
Stream(Stream const &) noexcept=default
int device() const noexcept
Return the device that owns this stream.
Definition runtime.cpp:280
void wait_on(Completion const &completion) const
Make this stream wait for completion before executing subsequent work.
Definition runtime.cpp:304
Stream(Stream &&other) noexcept=default
friend class StreamPool
Definition runtime.hpp:100
Stream & operator=(Stream const &) noexcept=default
Stream & operator=(Stream &&other) noexcept=default
locale_t value
Definition data_table.cpp:49
CUDA device discovery and immutable hardware capability snapshots.
Definition cublas/execution.hpp:18
Runtime & runtime()
Return the installed runtime or fail when CUDA was not initialized.
Definition runtime.cpp:811
Runtime initialize(RuntimeConfig config)
Install and return a scoped process-wide CUDA runtime owner.
Definition runtime.cpp:807
bool is_initialized() noexcept
Return whether a process-wide CUDA runtime is currently installed.
Definition runtime.cpp:809
DeviceResources & device_resources()
Return canonical resources for the installed runtime's default device.
Definition runtime.cpp:820
std::size_t span
Definition presentation.cpp:2017
Configuration for one device's mutable CUDA resources.
Definition runtime.hpp:226
Device device
Definition runtime.hpp:227
std::size_t stream_count
Definition runtime.hpp:228
Configuration for one scoped process-wide CUDA runtime installation.
Definition runtime.hpp:308
Configuration for a device-local idle-stream pool.
Definition runtime.hpp:167
std::size_t stream_count
Definition runtime.hpp:169
int device
Definition runtime.hpp:168
#define CHECK(cond,...)
Definition trace.hpp:299