Skip to content

Commit 95ffdc7

Browse files
committed
Add specification for kernel binary update
1 parent 8761d40 commit 95ffdc7

File tree

1 file changed

+199
-22
lines changed

1 file changed

+199
-22
lines changed

sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc

+199-22
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,95 @@ Parameters:
556556

557557
|===
558558

559+
==== Dynamic Command Groups
560+
561+
[source,c++]
562+
----
563+
namespace ext::oneapi::experimental{
564+
class dynamic_command_group {
565+
public:
566+
dynamic_command_group(
567+
command_graph<graph_state::modifiable> graph, std::vector<std::function<void(handler &)>> cgfList);
568+
569+
void set_active_cgf(int cgfIndex);
570+
};
571+
----
572+
573+
Dynamic command-groups can be added as nodes to a graph. They provide a mechanism that
574+
allows updating the command-group function of a node after the graph is finalized.
575+
There is always one command-group function in the dynamic command-group that is set as active.
576+
577+
===== Limitations
578+
579+
Dynamic command-groups can only be used to update kernels. Trying to update a command group
580+
function that contains memory operations will result in an error.
581+
582+
All the command-group functions in a dynamic command group must have identical dependencies.
583+
It is not allowed for a dynamic command group to have command-group functions that would
584+
result in a change to the graph topology when set to active. In practice, this means that
585+
any calls to `handler.depends_on()` must be identical for all the command-group functions
586+
in a dynamic command-group.
587+
588+
See <<executable-graph-update, Executable Graph Update>> for more information
589+
about updating command-groups.
590+
591+
Table {counter: tableNumber}. Member functions of the `dynamic_command_group` class.
592+
[cols="2a,a"]
593+
|===
594+
|Member Function|Description
595+
596+
|
597+
[source,c++]
598+
----
599+
dynamic_command_group(command_graph<graph_state::modifiable> graph, std::vector<std::function<void(handler &)>> cgfList);
600+
----
601+
|Constructs a dynamic command group object that can be added as a node to a command_graph.
602+
603+
Parameters:
604+
605+
* `graph` - Graph to be associated with this `dynamic_command_group`.
606+
* `cgfList` - The list of command-group functions that can be activated for this dynamic command group.
607+
The command-group function at index 0 will be active by default.
608+
609+
Exceptions:
610+
611+
* Throws synchronously with error code `invalid` if the graph wasn't created with
612+
the `property::graph::assume_buffer_outlives_graph` property and the `dynamic_command_group`
613+
is created with command-group functions that use buffers. See the
614+
<<assume-buffer-outlives-graph-property, Assume-Buffer-Outlives-Graph>>
615+
property for more information.
616+
617+
* Throws with error code `invalid` if the `dynamic_command_group` is created with
618+
command-group functions that are not kernel executions.
619+
620+
|
621+
[source,c++]
622+
----
623+
void set_active_cgf(int cgfIndex);
624+
----
625+
626+
| Sets the command-group function with index `cgfIndex` as active. The index of the
627+
command-group function in a `dynamic_command_group` is identical to its index in the
628+
`cgfList` vector when it was passed to the `dynamic_command_group` constructor.
629+
630+
This change will be reflected immediately in the modifiable graph which contains this
631+
`dynamic_command_group`. The new value will not be reflected in any executable graphs
632+
created from that modifiable graph until `command_graph::update()` is called, passing
633+
the modified nodes, or a new executable graph is finalized from the modifiable graph.
634+
635+
Setting `cgfIndex` to the index of the currently active command-group function is
636+
a no-op.
637+
638+
Parameters:
639+
640+
* `cgfIndex` - The index of the command-group function that should be set as active.
641+
642+
Exceptions:
643+
644+
* Throw with error code `invalid` if `cgfIndex` is not a valid index.
645+
646+
|===
647+
559648
==== Depends-On Property
560649

561650
[source,c++]
@@ -631,6 +720,8 @@ public:
631720
template<typename T>
632721
node add(T cgf, const property_list& propList = {});
633722
723+
node add(dynamic_command_group& dcg, const property_list& propList = {});
724+
634725
void make_edge(node& src, node& dest);
635726
636727
void print_graph(std::string path, bool verbose = false) const;
@@ -711,21 +802,39 @@ Updates to a graph will be scheduled after any in-flight executions of the same
711802
graph and will not affect previous submissions of the same graph. The user is
712803
not required to wait on any previous submissions of a graph before updating it.
713804

714-
The only type of nodes that are currently able to be updated in a graph are
715-
kernel execution nodes.
716-
717-
The aspects of a kernel execution node that can be configured during update are:
718-
719-
* Parameters to the kernel.
720-
* Execution ND-Range of the kernel.
721-
722805
To update an executable graph, the `property::graph::updatable` property must
723806
have been set when the graph was created during finalization. Otherwise, an
724807
exception will be thrown if a user tries to update an executable graph. This
725808
guarantee allows the backend to provide a more optimized implementation, if
726809
possible.
727810

728-
===== Individual Node Update
811+
===== Supported Features:
812+
813+
The only type of nodes that are currently able to be updated in a graphs are
814+
kernel execution nodes.
815+
816+
There is two different API's that can be used to update a graph:
817+
818+
* <individual-node-update, Individual Node Update>> which allows updating
819+
individual nodes of a command-graph.
820+
* <<whole-graph-update, Whole Graph Update>> which allows updating the
821+
entirety of the graph simultaneously by using another graph as a
822+
reference.
823+
824+
The aspects of a kernel execution node that can be changed during update are
825+
different depending on the API used to perform the update:
826+
827+
* For the <<individual-node-update, Individual Node Update>> API it's possible to update
828+
the kernel function, the parameters to the kernel, and the ND-Range.
829+
* For the <<whole-graph-update, Whole Graph Update>> API, only the parameters of the kernel
830+
and the ND-Range can be updated.
831+
832+
===== Individual Node Update [[individual-node-update]]
833+
834+
Individual nodes of an executable graph can be updated directly. Depending on the attribute
835+
of the node that requires updating, different API's should be used:
836+
837+
===== Parameter Updates:
729838

730839
Parameters to individual nodes in a graph in the `executable` state can be
731840
updated between graph executions using dynamic parameters. A `dynamic_parameter`
@@ -739,14 +848,6 @@ Parameter updates are performed using a `dynamic_parameter` instance by calling
739848
not registered, even if they use the same parameter value as a
740849
`dynamic_parameter`.
741850

742-
The other node configuration that can be updated is the execution range of the
743-
kernel, this can be set through `node::update_nd_range()` or
744-
`node::update_range()` but does not require any prior registration.
745-
746-
The executable graph can then be updated by passing the updated nodes to
747-
`command_graph<graph_state::executable>::update(node& node)` or
748-
`command_graph<graph_state::executable>::update(const std::vector<node>& nodes)`.
749-
750851
Since the structure of the graph became fixed when finalizing, updating
751852
parameters on a node will not change the already defined dependencies between
752853
nodes. This is important to note when updating buffer parameters to a node,
@@ -762,6 +863,41 @@ dynamic parameter for the buffer can be registered with all the nodes which
762863
use the buffer as a parameter. Then a single `dynamic_parameter::update()` call
763864
will maintain the graphs data dependencies.
764865

866+
===== Execution Range Updates:
867+
868+
Another configuration that can be updated is the execution range of the
869+
kernel, this can be set through `node::update_nd_range()` or
870+
`node::update_range()` but does not require any prior registration.
871+
872+
An alternative way to update the execution range of a node is to do so while
873+
updating command groups as described in the next section.
874+
875+
===== Command Group Updates:
876+
877+
The command-groups of a kernel node can be updated using dynamic command-groups.
878+
Dynamic command-groups allow replacing the command-group function of a kernel
879+
node with a different one. This effectively allows updating the kernel binaries, the
880+
argument types, the number of arguments and/or the execution ranges.
881+
882+
Command-group updates are performed by creating an instance of the
883+
`dynamic_command_group` class. A dynamic command-group is created with a modifiable
884+
state graph and a list of possible command-group functions. Command-group functions
885+
within a dynamic command-group can then be set to active by using the member function
886+
`dynamic_command_group::setActiveCgf()`.
887+
888+
Dynamic command-groups are compatible with dynamic parameters. This means that
889+
dynamic parameters can be used in command-group functions that are part of
890+
dynamic command-groups. Updates to such dynamic parameters will be reflected
891+
in the command-group functions once they are activated.
892+
893+
===== Finalizing updates:
894+
895+
Updating a node using the methods mentioned above will take effect immediately
896+
for nodes in modifiable command-graphs. However, for graphs that are in the executable
897+
state, in order to finalize the update, the updated nodes must be passed to
898+
`command_graph<graph_state::executable>::update(node& node)` or
899+
`command_graph<graph_state::executable>::update(const std::vector<node>& nodes)`.
900+
765901
===== Whole Graph Update [[whole-graph-update]]
766902

767903
A graph in the executable state can have all of its nodes updated using the
@@ -1042,6 +1178,42 @@ Exceptions:
10421178
|
10431179
[source,c++]
10441180
----
1181+
node add(dynamic_command_group& dcg, const property_list& propList = {});
1182+
----
1183+
1184+
| Adds the dynamic command-group `dcg` as a node to the graph and sets the
1185+
current active command-group function in `dcg` as the executable for future
1186+
executions of this graph node.
1187+
1188+
The current active command-group function in `dcg` will be executed asynchronously
1189+
when the graph is submitted to a queue. The requisites of this command-group
1190+
function will be used to identify any dependent nodes in the graph
1191+
to form edges with. The other command-group functions in `dcg` will be captured
1192+
into the graph but will not be executed in a graph submission unless they are
1193+
set to active.
1194+
1195+
Constraints:
1196+
1197+
* This member function is only available when the `command_graph` state is
1198+
`graph_state::modifiable`.
1199+
1200+
Parameters:
1201+
1202+
* `dcg` - Dynamic command-group object to be added as a node.
1203+
1204+
* `propList` - Zero or more properties can be provided to the constructed node
1205+
via an instance of `property_list`. The `property::node::depends_on` property
1206+
can be passed here with a list of nodes to create dependency edges on.
1207+
1208+
Returns: The dynamic command-group object node which has been added to the graph.
1209+
1210+
Exceptions:
1211+
1212+
* Throws synchronously with error code `invalid` if a queue is recording
1213+
commands to the graph.
1214+
|
1215+
[source,c++]
1216+
----
10451217
void make_edge(node& src, node& dest);
10461218
----
10471219

@@ -1157,8 +1329,9 @@ void update(node& node);
11571329
----
11581330

11591331
| Updates an executable graph node that corresponds to `node`. `node` must be a
1160-
kernel execution node. Kernel arguments and the ND-range of the node will be
1161-
updated inside the executable graph to reflect the current values in `node`.
1332+
kernel execution node. Kernel arguments and the command-group function of the
1333+
node will be updated inside the executable graph to reflect the current values
1334+
in `node`.
11621335

11631336
Updating these values will not change the structure of the graph.
11641337

@@ -1190,9 +1363,9 @@ void update(const std::vector<node>& nodes);
11901363
----
11911364

11921365
| Updates all executable graph nodes that corresponds to the nodes contained in
1193-
`nodes`. All nodes must be kernel nodes. Kernel arguments and the ND-range of
1194-
each node will be updated inside the executable graph to reflect the current
1195-
values in each node in `nodes`.
1366+
`nodes`. All nodes must be kernel nodes. Kernel arguments and the
1367+
command-group function of each node will be updated inside the executable graph
1368+
to reflect the current values in each node in `nodes`.
11961369

11971370
Updating these values will not change the structure of the graph.
11981371

@@ -1712,6 +1885,10 @@ the call to `queue::submit()` or `command_graph::add()` along with the calls to
17121885
handler functions and this will not be reflected on future executions of the
17131886
graph.
17141887

1888+
Similarly, any command-group function inside a `dynamic_command_group` will be
1889+
evaluated once, in index order, when submitted to the graph using
1890+
`command_graph::add()`.
1891+
17151892
Any code like this should be moved to a separate host-task and added to the
17161893
graph via the recording or explicit APIs in order to be compatible with this
17171894
extension.

0 commit comments

Comments
 (0)