14#include <oneapi/tbb/concurrent_queue.h>
15#include <oneapi/tbb/parallel_for.h>
16#include <oneapi/tbb/task.h>
17#include <oneapi/tbb/task_arena.h>
18#include <oneapi/tbb/task_group.h>
20#include <uni20/config.hpp>
29inline void service_tbb_task_registry_debug_requests()
31#if UNI20_DEBUG_ASYNC_TASKS
57class TbbNumaScheduler;
69 explicit TbbScheduler(
int max_concurrency = oneapi::tbb::task_arena::automatic,
71 : arena_(max_concurrency, max_concurrency == 1 ? 0 : 1,
72 oneapi::tbb::task_arena::priority::normal, oneapi::tbb::task_arena::leave_policy::fast),
73 batch_options_(
std::move(batch_options)), paused_(false)
82 : arena_(constraints, constraints.max_concurrency == 1 ? 0 : 1,
83 oneapi::tbb::task_arena::priority::normal, oneapi::tbb::task_arena::leave_policy::fast),
84 batch_options_(
std::move(batch_options)), paused_(false)
99 if (t.set_scheduler(
this)) this->
enqueue_task(std::move(t));
111 detail::service_tbb_task_registry_debug_requests();
113 detail::service_tbb_task_registry_debug_requests();
119 std::scoped_lock lock(pause_mutex_);
120 paused_.store(
true, std::memory_order_release);
126 std::vector<TaskHandle> drained;
128 std::scoped_lock lock(pause_mutex_);
129 paused_.store(
false, std::memory_order_release);
131 while (queue_.try_pop(h))
133 drained.push_back(h);
137 for (
auto h : drained)
139 TRACE_MODULE(ASYNC,
"scheduling coroutine", h.coroutine());
156 throw async_state_error(
"TbbScheduler pending wait requires a readiness notification");
158 arena_.execute([&] { this->wait_in_arena(request); });
164 if (batch.
size() == 0)
return;
169 if (arena_.max_concurrency() == 1)
171 for (std::size_t index = 0; index < batch.size(); ++index)
178 oneapi::tbb::parallel_for(std::size_t{0}, batch.
size(), [&](std::size_t index) { batch(index); });
182 std::size_t
const runner_count =
183 std::min(*batch_options_.
maximum_concurrency,
static_cast<std::size_t
>(arena_.max_concurrency()));
184 if (runner_count >= batch.
size())
186 oneapi::tbb::parallel_for(std::size_t{0}, batch.
size(), [&](std::size_t index) { batch(index); });
190 std::atomic<std::size_t> next_index{0};
191 oneapi::tbb::parallel_for(
192 std::size_t{0}, runner_count,
196 std::size_t
const index = next_index.fetch_add(1, std::memory_order_relaxed);
197 if (index >= batch.
size())
return;
201 oneapi::tbb::simple_partitioner{});
205 bool accepts_route(TaskRoute route)
const noexcept override
210 bool can_direct_transfer(TaskHandle, TaskHandle)
const noexcept override {
return true; }
213 void reschedule(BasicTask&& t)
override { this->enqueue_task(std::move(t)); }
215 class SuspendedWait {
217 void install(oneapi::tbb::task::suspend_point point)
noexcept
219 oneapi::tbb::task::suspend_point point_to_resume =
nullptr;
221 std::scoped_lock lock(mutex_);
223 if (signaled_ && !resume_issued_)
225 resume_issued_ =
true;
226 point_to_resume = point_;
229 if (point_to_resume) oneapi::tbb::task::resume(point_to_resume);
232 void signal() noexcept
234 oneapi::tbb::task::suspend_point point_to_resume =
nullptr;
236 std::scoped_lock lock(mutex_);
238 if (point_ && !resume_issued_)
240 resume_issued_ =
true;
241 point_to_resume = point_;
244 if (point_to_resume) oneapi::tbb::task::resume(point_to_resume);
249 oneapi::tbb::task::suspend_point point_{
nullptr};
250 bool signaled_{
false};
251 bool resume_issued_{
false};
254 void wait_in_arena(WaitRequest
const& request)
256 while (!request.is_ready())
258 detail::service_tbb_task_registry_debug_requests();
259 auto wait = std::make_shared<SuspendedWait>();
260 request.notify_when_ready([weak_wait = std::weak_ptr<SuspendedWait>(wait)]()
noexcept {
261 if (
auto active = weak_wait.lock())
active->signal();
266 if (request.is_ready())
return;
267 oneapi::tbb::task::suspend([wait](oneapi::tbb::task::suspend_point point) { wait->install(point); });
277 arena_.execute([&] { tg_.wait(); });
283 TRACE_MODULE(ASYNC,
"TBB scheduler enqueuing task", t.coroutine_handle());
284 if (
auto h = t.release_handle())
286 bool paused = paused_.load(std::memory_order_acquire);
294 std::scoped_lock lock(pause_mutex_);
295 if (paused_.load(std::memory_order_acquire))
302 this->dispatch_handle(h);
310 this->dispatch_handle_in_arena(arena_,
handle, {.scheduler =
"TbbScheduler"}, [] {});
319 template <
typename Prepare>
321 detail::TbbTaskAdmissionContext context, Prepare&& prepare)
323 detail::enqueue_tbb_task(
325 [
handle, prepare = std::forward<Prepare>(prepare)] {
329 detail::service_tbb_task_registry_debug_requests();
335 oneapi::tbb::task_arena arena_;
336 oneapi::tbb::task_group tg_;
338 std::atomic<bool> paused_;
339 std::mutex pause_mutex_;
340 oneapi::tbb::concurrent_queue<TaskHandle> queue_;
Exception hierarchy for async/dataflow operations.
static bool service_debug_requests()
Processes pending dump requests on the calling thread.
static void record_task_scheduled(std::coroutine_handle<> h)
Records the call stack where a coroutine was submitted to a scheduler.
Canonical host-oriented coroutine task type.
Definition async_task.hpp:196
Move-only promise-neutral ownership claim for a Uni20 coroutine.
Definition async_task.hpp:103
Scheduler interface for initial AsyncTask submission and host-side progress.
Definition scheduler.hpp:89
std::function< bool()> WaitPredicate
Definition scheduler.hpp:127
Borrowed type-erased description of a synchronous lightweight task batch.
Definition scheduler.hpp:28
auto size() const noexcept -> std::size_t
Return the number of independent work items.
Definition scheduler.hpp:45
Non-owning erased identity for one Uni20 coroutine frame.
Definition async_task.hpp:59
static void resume_and_track(TaskHandle handle)
Resume a coroutine handle while recording the running transition.
Definition async_task_promise.hpp:400
NUMA-aware scheduler that balances work across per-node TBB arenas.
Definition tbb_numa_scheduler.hpp:24
Definition tbb_scheduler.hpp:59
void resume() override
Unpause the scheduler, and execute any tasks that have been queued.
Definition tbb_scheduler.hpp:124
void dispatch_handle_in_arena(oneapi::tbb::task_arena &arena, TaskHandle handle, detail::TbbTaskAdmissionContext context, Prepare &&prepare)
Submit one activation to an arena through the shared task group.
Definition tbb_scheduler.hpp:320
void wait_for(const WaitPredicate &is_ready) override
Accept an already-satisfied predicate; pending TBB waits require a WaitRequest notification.
Definition tbb_scheduler.hpp:147
void enqueue_task(BasicTask &&t)
Enqueue one task through the scheduler's domain-routing hook.
Definition tbb_scheduler.hpp:281
TbbScheduler(oneapi::tbb::task_arena::constraints constraints, TbbSchedulerBatchOptions batch_options={})
Construct a TBB scheduler constrained to a specific NUMA node.
Definition tbb_scheduler.hpp:81
void help_while_waiting(const WaitPredicate &is_ready) override
Allow a scheduler to advance queued work while a thread is blocking.
Definition tbb_scheduler.hpp:144
TbbScheduler(int max_concurrency=oneapi::tbb::task_arena::automatic, TbbSchedulerBatchOptions batch_options={})
Construct a TBB scheduler with a given arena concurrency.
Definition tbb_scheduler.hpp:69
void pause() override
Pause the scheduler. Don't execute scheduled tasks, but instead add them to a queue.
Definition tbb_scheduler.hpp:117
void wait_for_submitted_tasks()
Wait for every activation registered with the shared task group.
Definition tbb_scheduler.hpp:275
~TbbScheduler() noexcept override
Definition tbb_scheduler.hpp:89
virtual void dispatch_handle(TaskHandle handle)
Route one runnable task activation to its execution arena.
Definition tbb_scheduler.hpp:308
void run_all()
Block until all tasks scheduled on this scheduler are complete.
Definition tbb_scheduler.hpp:108
void wait_for(WaitRequest const &request) override
Wait for targeted readiness while allowing the arena to execute other work.
Definition tbb_scheduler.hpp:152
void schedule(AsyncTask &&t) override
Schedule a coroutine for initial execution.
Definition tbb_scheduler.hpp:96
Base class for invalid async state transitions or accesses.
Definition async_errors.hpp:20
cuda::ResourceLease< HandleSlot > handle
Definition cublas/execution.cpp:33
This represents the reverse-mode adjoint for functions of complex variables, assuming a real-valued s...
Definition async/async.hpp:26
Defines internal task routing and the host-oriented scheduler interface.
Readiness predicate and optional targeted wakeup registration for a blocking wait.
Definition scheduler.hpp:133
WaitPredicate is_ready
Predicate that reports whether the requested value is available.
Definition scheduler.hpp:135
WaitWakeupRegistration notify_when_ready
Register a non-throwing wakeup, including when readiness races with registration.
Definition scheduler.hpp:142
Runtime policy for synchronous lightweight batches executed by a TBB scheduler.
Definition tbb_scheduler.hpp:39
std::optional< std::size_t > maximum_concurrency
Maximum number of concurrently executing batch runners; null uses ordinary parallel_for partitioning.
Definition tbb_scheduler.hpp:41
Selects the task-registry implementation for the current build mode.
Internal non-blocking oneTBB arena admission helper.
#define CHECK(cond,...)
Definition trace.hpp:299
#define TRACE_MODULE(m,...)
Definition trace.hpp:149