Adopting ISO C++ sender/receiver model #11646
AerialMantis
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Note: this is still an early draft to begin the discussion, much of this will need to be further defined.
Overview
This discussion proposes changes to the SYCL interface which reflect a new design for the SYCL execution model based on the proposed ISO C++ sender/receiver model (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2300r7.html).
The motivation for this is:
If we want to achieve these goals it will require a change to the SYCL interface, but we should ensure this change is minimal to avoid big breaking changes for users, and we should do it just once if possible.
Motivation
All command functions such as
submitor shortcut functions likeparallel_forreturn aneventwhich allows users to create dependency chains and synchronize with submitted commands. However, theeventclass in SYCL conflates usage for dependencies and usage for synchronizing with submitted commands.Furthermore, the SYCL execution model currently does not specify whether commands submitted to the runtime are executed eagerly or lazily. The user has no control over this and as a result must assume that they could be executed lazily and synchronize with the commands (via event wait, queue wait, or buffer destruction) in order to ensure the work has been enqueued to the backend.
This is evident by looking at two use cases.
In the first case, where users require low latency execution, i.e. commands being executed as soon after submission as possible, the SYCL specification cannot guarantee this. If the
eventis implemented as eager then the command is executed immediately, so no synchronization is required to ensure the command is executing. However, if theeventis implemented as lazy then the command will not execute immediately, and the only way to ensure this is to synchronize with theeventorqueueor the destruction of abufferwhich is being written to by the command.In the second case, where users wish to create task graphs, i.e. commands are collected and batched all together and the creation of native event objects can be elided. If the
eventis implemented as eager then the backend must provide a native backend event object for every command, even if it's never used, creating a performance overhead. If theeventis implemented as lazy then the creation of native backend event objects can be elided, however, theeventclass still requires synchronizations and query capabilities.Considered Solutions
There are a few different options which have been considered to solve this:
events; synchronization on an event may also synchronize with earlier events (https://github.com/AdaptiveCpp/AdaptiveCpp/blob/develop/doc/extensions.md#hipsycl_ext_coarse_grained_events).events.events; synchronization on an event may fail (https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/supported/sycl_ext_oneapi_discard_queue_events.asciidoc).queue/handlewhich either return aneventor don't ([SYCL][DOC] Add sycl_ext_oneapi_enqueue_functions #11491).Alternative Approach Using Sender/Receiver
Another option is to adopt the sender/receiver model of execution proposed in P2300 for ISO C++.
The sender/receiver model works by composing senders which are like
std::futurebut lazy, starting with a sender produced by scheduling on a particular execution resource and then adding commands via sender algorithms, which can then be synchronized with.In the sender/receiver model:
Receivers are not typically exposed to users.
To introduce the sender/receiver model in SYCL we would need to do the following:
get_scheduler()member function onqueuefor retrieving a scheduler.scheduleandensure_started, further algorithms could be added incrementally.submitand the shortcut functions such asparallel_for,memcpy, etc.Benefits of Using Sender/Receiver
There are a number of benefits of using the sender/receiver model.
Status of Senders/Receivers in ISO C++
The senders/receiver paper (P2300) is in review by the C++ committee, and it is hoped that it will be approved for C++26, however, if it isn't then it could be later before it's available in C++.
Example
Below is an example of SYCL using the sender/receiver model.
The above example can also be reprsented differently using the sender/receiver pipe syntax, here this is using the
parallel_forshortcut function.Proposal
Execution Stream
Introduce a new type;
execution_streamwhich represents the smallest granularity of execution resource for a backend, that is a single stream of execution and executes in order.SYCL Scheduler
Introduce a new type;
schedulerwhich conforms to the scheduler concept of P2300 and is associated with a SYCLqueueanddeviceto which work will be enqueued.Add a new member functions to the
queueandexecution_streamclasses;queue::get_schedulerandexecution_stream::get_scheduler()which return ascheduler.SYCL Senders
Introduce the concept of sender in SYCL as an object which represents a series of commands which have not yet been enqueued to the backend. Specify that there are two kinds of sender:
submit.Introduce the concept of implementation-defined sender types which conforms to the sender concept of P2300 and represents zero or more commands such as kernel launches or copies which have not yet been enqueued to the backend.
Introduce a new type
senderwhich provides a polymorphic wrapper to any implementation-defined sender type, providing a conversion operator for those types.SYCL Sender Factories
Introduce the
schedulefactory function as follows:Returns an empty implementation-defined sender which represents the transition to the target
devicewith the sender'squeueorexecution_stream.SYCL Sender Algorithms
Introduce all existing command functions (member functions of
queue) in SYCL 2020 as algorithms, includingsubmit,single_task,parallel_for,memcpy,memset,fill,copy,prefetchandmem_adviseas follows:Each function would behave as currently defined in SYCL 2020, but returning an implementation-defined sender representing the specified command as to be executed but not yet enqueued to the backend.
SYCL Sender Adapters
Introduce the
ensure_startedadapter function as follows:Takes a SYCL sender type, ensures that the commands it represents are enqueued to the backend and then returns a new implementation-defined sender type.
SYCL Sender Consumers
Introduce the
sync_waitconsumer function as follows:Takes a SYCL sender type, ensures that the commands it represents are enqueued to the backend and then synchronizes with the execution resource executing those commands before returning.
Note: in P2300
this_thread::sync_waitreturns astd::optional<std::tuple<>>, it needs to be considered whether SYCL should implement this as in P2300 or returnsvoid.Beta Was this translation helpful? Give feedback.
All reactions