@@ -281,11 +281,14 @@ represent data dependencies between two command groups captured as nodes.
281
281
Secondly, by using the `handler::depends_on()` mechanism inside a command group
282
282
captured as a node. However, for an event passed to `handler::depends_on()` to
283
283
create an edge, it must be an event returned from a queue
284
- submission captured by the same graph. Otherwise, a synchronous error will be
285
- thrown with error code `invalid`. `handler::depends_on()` can be
286
- used to express edges when a user is working with USM memory rather than SYCL
287
- buffers. Thirdly, for a graph recorded with an in-order queue, an edge is added
288
- automatically between two sequential command groups submitted to the in-order queue.
284
+ submission captured by the same graph. Passing events from other sources (other
285
+ graph submissions, regular SYCL submissions) will not create edges in the graph,
286
+ but will create runtime dependencies for a graph node on those other events.
287
+ `handler::depends_on()` can be used to express edges when a user is working with
288
+ USM memory rather than SYCL buffers. Thirdly, for a graph recorded with an
289
+ in-order queue, an edge is added automatically between two sequential command
290
+ groups submitted to the in-order queue.
291
+
289
292
|===
290
293
291
294
==== Sub-Graph
@@ -565,16 +568,24 @@ class depends_on {
565
568
public:
566
569
template<typename... NodeTN>
567
570
depends_on(NodeTN... nodes);
571
+
572
+ depends_on(const event& ev);
573
+
574
+ depends_on(const std::vector<event>& events);
568
575
};
569
576
}
570
577
----
571
578
572
579
The API for explicitly adding nodes to a `command_graph` includes a
573
580
`property_list` parameter. This extension defines the `depends_on` property to
574
- be passed here. `depends_on` defines any `node` objects for the created node to
575
- be dependent on, and therefore form an edge with. These nodes are in addition to
576
- the dependent nodes identified from the command-group requisites of the created
577
- node.
581
+ be passed here. `depends_on` may be used in two ways:
582
+
583
+ * Passing nodes from the same command_graph which will create dependencies and
584
+ graph edges between those nodes and the node being added.
585
+
586
+ * Passing SYCL events will create runtime dependencies for execution of the
587
+ graph node but will only create edges if those events are associated with other
588
+ nodes in the same graph.
578
589
579
590
==== Depends-On-All-Leaves Property
580
591
[source,c++]
@@ -646,6 +657,8 @@ public:
646
657
647
658
void update(node& node);
648
659
void update(const std::vector<node>& nodes);
660
+
661
+ event get_event(const node& n);
649
662
};
650
663
651
664
} // namespace sycl::ext::oneapi::experimental
@@ -761,6 +774,15 @@ dynamic parameter for the buffer can be registered with all the nodes which
761
774
use the buffer as a parameter. Then a single `dynamic_parameter::update()` call
762
775
will maintain the graphs data dependencies.
763
776
777
+ ===== Node Event Dependency Update
778
+
779
+ Event dependencies for nodes can be updated using <<dynamic-events, Dynamic
780
+ Events>> in a similar usage to Dynamic Parameters.
781
+
782
+ Event updates are performed using a `dynamic_event` instance and calling
783
+ `dynamic_event::update()` to update all the associated event dependencies of
784
+ nodes which the `dynamic_event` is associated with.
785
+
764
786
==== Graph Properties [[graph-properties]]
765
787
766
788
===== No-Cycle-Check Property
@@ -1094,6 +1116,15 @@ std::vector<node> get_root_nodes() const;
1094
1116
----
1095
1117
|Returns a list of all nodes in the graph which have no dependencies.
1096
1118
1119
+ |
1120
+ [source,c++]
1121
+ ----
1122
+ event get_event(const node& n);
1123
+ ----
1124
+ |Returns a SYCL event which represents the completion of node `n` which is valid
1125
+ only for the next execution of the graph. This event can be used as a dependency
1126
+ in the same way as normal SYCL events.
1127
+
1097
1128
|===
1098
1129
1099
1130
Table {counter: tableNumber}. Member functions of the `command_graph` class for
@@ -1571,6 +1602,89 @@ a normal SYCL command-group submission.
1571
1602
associated with the graph node resulting from this command-group submission is
1572
1603
different from the one with which the dynamic_parameter was created.
1573
1604
1605
+ |===
1606
+
1607
+ === Dynamic Events [[dynamic-events]]
1608
+
1609
+ [source,c++]
1610
+ ----
1611
+ namespace ext::oneapi::experimental{
1612
+ class dynamic_event{
1613
+ dynamic_event();
1614
+ dynamic_event(const event& ev);
1615
+
1616
+ void update(const event& ev);
1617
+ };
1618
+ }
1619
+ ----
1620
+
1621
+ Dynamic events represent SYCL events from outside of a given `command_graph`
1622
+ (either obtained from normal SYCL operations or from another `command_graph`)
1623
+ that nodes in that graph may depend on. Dynamic events also allow for these
1624
+ dependent events to be updated between graph executions.
1625
+
1626
+ Dynamic events can be used to add dependencies to a graph node in the same way
1627
+ that regular SYCL events can, by passing them as parameters to
1628
+ `handler::depends_on()` inside the CGF which represents the node.
1629
+
1630
+ [source,c++]
1631
+ ----
1632
+ // Obtain an event from a normal queue submission
1633
+ event OutsideEvent = queue.submit(...);
1634
+
1635
+ // Create a dynamic event to wrap that event
1636
+ ext::oneapi::experimental::dynamic_event DynEvent {OutsideEvent};
1637
+
1638
+ // Add a graph node which depends on that dynamic event
1639
+ Graph.add([&](handler& CGH){
1640
+ CGH.depends_on(DynEvent);
1641
+ CGH.parallel_for(...);
1642
+ });
1643
+ ----
1644
+ Dynamic events created with an event from a `command_graph` cannot then be
1645
+ associated with other nodes in that same graph as this would change the shape of
1646
+ the graph. Attempting to call `handler::depends_on()` with such a
1647
+ `dynamic_event` in that situation will result in an error.
1648
+
1649
+ Dynamic events can be created with no event but must be updated with a valid
1650
+ event before any executable graph which depends on that event is executed.
1651
+ Failing to do so will result in an error.
1652
+
1653
+ Table {counter: tableNumber}. Member functions of the `dynamic_event` class.
1654
+ [cols="2a,a"]
1655
+ |===
1656
+ |Member function|Description
1657
+
1658
+ |
1659
+ [source,c++]
1660
+ ----
1661
+ dynamic_event();
1662
+ ----
1663
+
1664
+ | Constructs a default `dynamic_event` which is not associated with any SYCL event.
1665
+
1666
+ |
1667
+ [source,c++]
1668
+ ----
1669
+ dynamic_event(const event& ev);
1670
+ ----
1671
+
1672
+ | Constructs a `dynamic_event` which is associated with the SYCL event `ev`.
1673
+
1674
+
1675
+ |
1676
+ [source,c++]
1677
+ ----
1678
+ void update(const event& ev);
1679
+ ----
1680
+
1681
+ | Updates the SYCL event associated with `dynamic_event`. This update will be
1682
+ reflected immediately in the associated modifiable graph nodes. An executable
1683
+ graph can then be updated to reflect these new event dependencies using
1684
+ <<executable-graph-update, Executable Graph Update>>.
1685
+
1686
+
1687
+
1574
1688
|===
1575
1689
1576
1690
=== Thread Safety
@@ -1646,26 +1760,6 @@ of failure. The following list describes the behavior that changes during
1646
1760
recording mode. Features not listed below behave the same in recording mode as
1647
1761
they do in non-recording mode.
1648
1762
1649
- ==== Event Limitations
1650
-
1651
- For queue submissions that are being recorded to a modifiable `command_graph`,
1652
- the only events that can be used as parameters to `handler::depends_on()`, or
1653
- as dependent events for queue shortcuts like `queue::parallel_for()`, are events
1654
- that have been returned from queue submissions recorded to the same modifiable
1655
- `command_graph`.
1656
-
1657
- Other limitations on the events returned from a submission to a queue in the
1658
- recording state are:
1659
-
1660
- - Calling `event::get_info<info::event::command_execution_status>()` or
1661
- `event::get_profiling_info()` will throw synchronously with error code `invalid`.
1662
-
1663
- - A host-side wait on the event will throw synchronously with error
1664
- code `invalid`.
1665
-
1666
- - Using the event outside of the recording scope will throw synchronously with error code
1667
- `invalid`.
1668
-
1669
1763
==== Queue Limitations
1670
1764
1671
1765
A host-side wait on a queue in the recording state is an error and will
0 commit comments