Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
cublas/task_awaiters.hpp
Go to the documentation of this file.
1#pragma once
2
12
13#include <atomic>
14#include <optional>
15
16namespace uni20::cublas
17{
18
21 private cuda::detail::ResourceWaiter<HandleSlot>,
22 private cuda::detail::StreamWaiter {
23 public:
24 explicit ExecutionAcquireAwaiter(ExecutionPool& pool) noexcept
25 : cuda::detail::ResourceWaiter<HandleSlot>(&ExecutionAcquireAwaiter::handle_available),
26 cuda::detail::StreamWaiter(&ExecutionAcquireAwaiter::stream_available), pool_(&pool)
27 {}
28
33
34 [[nodiscard]] bool await_ready()
35 {
36 handle_ = pool_->handles_.try_acquire();
37 if (!handle_) return false;
38 stream_ = pool_->streams_->try_acquire();
39 return stream_.has_value();
40 }
41
42 bool await_suspend(std::coroutine_handle<async::CudaTaskPromise> handle) noexcept
43 {
44 auto current = async::TaskHandle::from(handle);
45 state_.store(registration_state::registering, std::memory_order_relaxed);
46 task_ = handle.promise().take_ownership();
48
49 this->advance();
50
51 auto const prior = state_.exchange(registration_state::suspended, std::memory_order_acq_rel);
52 if (prior == registration_state::ready) async::BasicTask::reschedule(std::move(task_));
53 return true;
54 }
55
57 {
58 CHECK(handle_.has_value());
59 CHECK(stream_.has_value());
60
61 int current_device = -1;
62 cuda::check(cudaGetDevice(&current_device), "cudaGetDevice after cuBLAS execution-resource acquisition");
63 CHECK_EQUAL(current_device, pool_->device(), "CUDA task resumed outside the cuBLAS pool's device");
64 return pool_->make_lease(std::move(*handle_), std::move(*stream_));
65 }
66
67 private:
68 enum class registration_state
69 {
70 registering,
71 suspended,
72 ready
73 };
74
75 void advance() noexcept
76 {
77 if (!handle_)
78 {
79 auto handle = pool_->handles_.acquire_or_enqueue(static_cast<cuda::detail::ResourceWaiter<HandleSlot>&>(*this));
80 if (!handle) return;
81 handle_ = std::move(*handle);
82 }
83
84 auto stream = pool_->streams_->acquire_or_enqueue(static_cast<cuda::detail::StreamWaiter&>(*this));
85 if (!stream) return;
86 stream_ = std::move(*stream);
87 this->publish_ready();
88 }
89
90 void publish_ready() noexcept
91 {
92 auto const prior = state_.exchange(registration_state::ready, std::memory_order_acq_rel);
93 if (prior == registration_state::suspended) async::BasicTask::reschedule(std::move(task_));
94 }
95
96 static void handle_available(cuda::detail::ResourceWaiter<HandleSlot>& waiter,
97 cuda::ResourceLease<HandleSlot> handle) noexcept
98 {
99 auto& self = static_cast<ExecutionAcquireAwaiter&>(waiter);
100 self.handle_ = std::move(handle);
101 self.advance();
102 }
103
104 static void stream_available(cuda::detail::StreamWaiter& waiter, cuda::Stream stream) noexcept
105 {
106 auto& self = static_cast<ExecutionAcquireAwaiter&>(waiter);
107 self.stream_ = std::move(stream);
108 self.publish_ready();
109 }
110
111 ExecutionPool* pool_;
112 std::optional<cuda::ResourceLease<HandleSlot>> handle_;
113 std::optional<cuda::Stream> stream_;
114 async::BasicTask task_;
115 std::atomic<registration_state> state_{registration_state::registering};
116};
117
119[[nodiscard]] inline ExecutionAcquireAwaiter acquire_execution(ExecutionPool& pool) noexcept
120{
121 return ExecutionAcquireAwaiter(pool);
122}
123
124} // namespace uni20::cublas
Move-only promise-neutral ownership claim for a Uni20 coroutine.
Definition async_task.hpp:103
static void reschedule(BasicTask task)
Reschedule a task when it becomes the sole ownership claimant.
Definition async_task_impl.hpp:11
static TaskHandle from(std::coroutine_handle< Promise > handle) noexcept
Definition async_task_promise.hpp:991
static void note_suspended(TaskHandle handle) noexcept
Record that a coroutine has suspended and is waiting for resumption.
Definition async_task_promise.hpp:370
Awaiter that reserves a cuBLAS handle before waiting for an idle stream.
Definition cublas/task_awaiters.hpp:22
ExecutionAcquireAwaiter(ExecutionPool &pool) noexcept
Definition cublas/task_awaiters.hpp:24
ExecutionLease await_resume()
Definition cublas/task_awaiters.hpp:56
ExecutionAcquireAwaiter(ExecutionAcquireAwaiter &&)=delete
ExecutionAcquireAwaiter & operator=(ExecutionAcquireAwaiter const &)=delete
ExecutionAcquireAwaiter & operator=(ExecutionAcquireAwaiter &&)=delete
ExecutionAcquireAwaiter(ExecutionAcquireAwaiter const &)=delete
bool await_suspend(std::coroutine_handle< async::CudaTaskPromise > handle) noexcept
Definition cublas/task_awaiters.hpp:42
bool await_ready()
Definition cublas/task_awaiters.hpp:34
Move-only dynamic pairing of one cuBLAS handle slot and one idle stream.
Definition cublas/execution.hpp:56
Device-local cuBLAS handle pool combined with a shared idle-stream pool.
Definition cublas/execution.hpp:98
int device() const noexcept
Return the CUDA device served by this execution pool.
Definition cublas/execution.hpp:114
std::optional< lease_type > try_acquire()
Try to acquire one idle resource without waiting.
Definition resource_pool.hpp:123
std::optional< lease_type > acquire_or_enqueue(waiter_type &waiter) noexcept
Register an internal awaiter unless a resource is immediately available.
Definition resource_pool.hpp:152
std::optional< Stream > acquire_or_enqueue(detail::StreamWaiter &waiter) noexcept
Register an internal awaiter unless a stream is immediately available.
Definition runtime.cpp:608
std::optional< Stream > try_acquire()
Try to lease one actually idle stream without waiting.
Definition runtime.cpp:576
cuda::ResourceLease< HandleSlot > handle
Definition cublas/execution.cpp:33
cuBLAS handle slots and dynamically paired stream execution leases.
Structured CUDA runtime failures and checked-call helpers.
Defines the CUDA task admission type and scheduler interface.
Definition cublas_error.cpp:11
ExecutionAcquireAwaiter acquire_execution(ExecutionPool &pool) noexcept
Acquire a cuBLAS handle and idle stream without blocking a CUDA task.
Definition cublas/task_awaiters.hpp:119
void check(cudaError_t status, std::string_view operation, std::optional< int > device, std::source_location where)
Raise when a CUDA runtime operation did not return cudaSuccess.
Definition cuda_error.cpp:44
Marker base for awaiters that require a CudaTaskPromise handle.
Definition async_task_promise.hpp:29
#define CHECK(cond,...)
Definition trace.hpp:299
#define CHECK_EQUAL(a, b,...)
Definition trace.hpp:309