@@ -556,6 +556,95 @@ Parameters:
556
556
557
557
|===
558
558
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
+
559
648
==== Depends-On Property
560
649
561
650
[source,c++]
@@ -631,6 +720,8 @@ public:
631
720
template<typename T>
632
721
node add(T cgf, const property_list& propList = {});
633
722
723
+ node add(dynamic_command_group& dcg, const property_list& propList = {});
724
+
634
725
void make_edge(node& src, node& dest);
635
726
636
727
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
711
802
graph and will not affect previous submissions of the same graph. The user is
712
803
not required to wait on any previous submissions of a graph before updating it.
713
804
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
-
722
805
To update an executable graph, the `property::graph::updatable` property must
723
806
have been set when the graph was created during finalization. Otherwise, an
724
807
exception will be thrown if a user tries to update an executable graph. This
725
808
guarantee allows the backend to provide a more optimized implementation, if
726
809
possible.
727
810
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:
729
838
730
839
Parameters to individual nodes in a graph in the `executable` state can be
731
840
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
739
848
not registered, even if they use the same parameter value as a
740
849
`dynamic_parameter`.
741
850
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
-
750
851
Since the structure of the graph became fixed when finalizing, updating
751
852
parameters on a node will not change the already defined dependencies between
752
853
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
762
863
use the buffer as a parameter. Then a single `dynamic_parameter::update()` call
763
864
will maintain the graphs data dependencies.
764
865
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
+
765
901
===== Whole Graph Update [[whole-graph-update]]
766
902
767
903
A graph in the executable state can have all of its nodes updated using the
@@ -1042,6 +1178,42 @@ Exceptions:
1042
1178
|
1043
1179
[source,c++]
1044
1180
----
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
+ ----
1045
1217
void make_edge(node& src, node& dest);
1046
1218
----
1047
1219
@@ -1157,8 +1329,9 @@ void update(node& node);
1157
1329
----
1158
1330
1159
1331
| 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`.
1162
1335
1163
1336
Updating these values will not change the structure of the graph.
1164
1337
@@ -1190,9 +1363,9 @@ void update(const std::vector<node>& nodes);
1190
1363
----
1191
1364
1192
1365
| 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`.
1196
1369
1197
1370
Updating these values will not change the structure of the graph.
1198
1371
@@ -1712,6 +1885,10 @@ the call to `queue::submit()` or `command_graph::add()` along with the calls to
1712
1885
handler functions and this will not be reflected on future executions of the
1713
1886
graph.
1714
1887
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
+
1715
1892
Any code like this should be moved to a separate host-task and added to the
1716
1893
graph via the recording or explicit APIs in order to be compatible with this
1717
1894
extension.
0 commit comments