From 8e21a1d5a3c00b0621450bb80691fd033e004a31 Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Tue, 20 Feb 2024 17:05:23 +0000 Subject: [PATCH 01/14] [SYCL][Graph] Update doc for UR PR moving reset commands to a dedicated cmd-list Update the design doc. Update the UR tag. --- sycl/doc/design/CommandGraph.md | 130 ++++++++++++------ .../design/images/L0_UR_command-buffer-v3.jpg | Bin 61543 -> 0 bytes .../design/images/L0_UR_command-buffer-v5.jpg | Bin 0 -> 76287 bytes sycl/plugins/unified_runtime/CMakeLists.txt | 10 +- 4 files changed, 91 insertions(+), 49 deletions(-) delete mode 100644 sycl/doc/design/images/L0_UR_command-buffer-v3.jpg create mode 100644 sycl/doc/design/images/L0_UR_command-buffer-v5.jpg diff --git a/sycl/doc/design/CommandGraph.md b/sycl/doc/design/CommandGraph.md index fe785175e81db..db432afffdd34 100644 --- a/sycl/doc/design/CommandGraph.md +++ b/sycl/doc/design/CommandGraph.md @@ -224,59 +224,107 @@ there are no parameters to take a wait-list, and the only sync primitive returned is blocking on host. In order to achieve the expected UR command-buffer enqueue semantics with Level -Zero, the adapter implementation adds extra commands to the Level Zero -command-list representing a UR command-buffer. - -* Prefix - Commands added to the start of the L0 command-list by L0 adapter. -* Suffix - Commands added to the end of the L0 command-list by L0 adapter. - -These extra commands operate on L0 event synchronisation primitives, used by the -command-list to interact with the external UR wait-list and UR return event -required for the enqueue interface. - -The `ur_exp_command_buffer_handle_t` class for this adapter contains a -*SignalEvent* which signals the completion of the command-list in the suffix, -and is reset in the prefix. This signal is detected by a new UR return event -created on UR command-buffer enqueue. - -There is also a *WaitEvent* used by the `ur_exp_command_buffer_handle_t` class -in the prefix to wait on any dependencies passed in the enqueue wait-list. -This WaitEvent is reset in the suffix. - -A command-buffer is expected to be submitted multiple times. Consequently, +Zero, the adapter implementation needs extra commands. + +* Prefix - Commands added **before** the graph workload. +* Suffix - Commands added **after** the graph workload. + +These extra commands operate on L0 event synchronisation primitives, +used by the command-list to interact with the external UR wait-list +and UR return event required for the enqueue interface. +Unlike the graph workload (i.e. commands needed to perform the graph workload) +the external UR wait-list and UR return event are submission dependent, +which mean they can change from one submission to the next. + +For performance concerns, the command-list that will execute the graph +workload is made only once (during the command-buffer finalization stage). +This allows the adapter to save time when submitting the command-buffer, +by executing only this command-list (i.e. without enqueuing any commands +of the graph workload). + +#### Prefix + +The prefix's commands aim to: +1. Handle the the list on events to wait on, which is passed by the runtime +when the UR command-buffer enqueue function is called. +As mentioned above, this list of events changes from one submission +to the next. +Consequently, managing this mutable dependency in the graph-workload +command-list implies rebuilding the command-list for each submission +(note that this can change with mutable command-list). +To avoid the signifiant time penalty of rebuilding this potentially large +command-list each time, we prefer to add an extra command handling the +wait list into another command-list (*wait command-list*). +This command-list consists of a single L0 command: a barrier that waits for +dependencies passed by the wait-list and signals a signal +called *WaitEvent* when the barrier is complete. +This *WaitEvent* is defined in the `ur_exp_command_buffer_handle_t` class. +In the front of the graph workload command list, an extra barrier command +waiting for this event is added (when the command-buffer is created). +This ensures that the graph workload does not start running before +the dependencies to be completed. +The *WaitEvent* event is reset in the suffix. + + +2. Reset events associated with the command-buffer except the +*WaitEvent* event. +Indeed, L0 events needs to be explicitly reset by an API call +(L0 command in our case). +Since a command-buffer is expected to be submitted multiple times, we need to ensure that L0 events associated with graph commands have not been signaled by a previous execution. These events are therefore reset to the -non-signaled state before running the actual graph associated commands. Note +non-signaled state before running the graph-workload command-list. Note that this reset is performed in the prefix and not in the suffix to avoid additional synchronization w.r.t profiling data extraction. - -If a command-buffer is about to be submitted to a queue with the profiling -property enabled, an extra command that copies timestamps of L0 events -associated with graph commands into a dedicated memory which is attached to the -returned UR event. This memory stores the profiling information that -corresponds to the current submission of the command-buffer. - -![L0 command-buffer diagram](images/L0_UR_command-buffer-v3.jpg) +We use a new command list (*reset command-list*) for performance concerns. +Indeed: + * This allows the *WaitEvent* to be signaled directly on the host if + the waiting list is empty, thus avoiding the need to submit a command list. + * Enqueuing a reset L0 command for all events in the command-buffer is time + consumming, especially for large graphs. + However, this task is not needed for every submission, but only once, when the + command-buffer is fixed, i.e. when the command-buffer is finalized. The + decorellation between the reset command-list and the wait command-list allow us to + create and enqueue the reset commands when finalizing the command-buffer, + and only create the wait command-list at submission. + +This command list is consist of a reset command for each of the graph commands +and another reset command for resetting the signal we use to signal the completion +of the graph workload. This signal is called *SignalEvent* and is defined in +in the `ur_exp_command_buffer_handle_t` class. + +#### Suffix + +The suffix's commands aim to: +1) Handle the completion of the graph workload and signal +an UR return event. +Thus, at the end of the graph workload command-list a command, which +signals the *SignalEvent*, is added (when the command-buffer is finalized). +In an additional command-list (*signal command-list*), a barrier waiting for +this event is also added. +This barrier signals, in turn, the UR return event that has be defined by +the runtime layer when calling the `urCommandBufferEnqueueExp` function. + +2) Manage the profiling. If a command-buffer is about to be submitted to +a queue with the profiling property enabled, an extra command that copies +timestamps of L0 events associated with graph commands into a dedicated +memory which is attached to the returned UR event. +This memory stores the profiling information that corresponds to +the current submission of the command-buffer. + +![L0 command-buffer diagram](images/L0_UR_command-buffer-v5.jpg) For a call to `urCommandBufferEnqueueExp` with an `event_list` *EL*, -command-buffer *CB*, and return event *RE* our implementation has to submit two -new command-lists for the above approach to work. One before +command-buffer *CB*, and return event *RE* our implementation has to submit +three new command-lists for the above approach to work. Two before the command-list with extra commands associated with *CB*, and the other -after *CB*. These two new command-lists are retrieved from the UR queue, which +after *CB*. These new command-lists are retrieved from the UR queue, which will likely reuse existing command-lists and only create a new one in the worst case. -The L0 command-list created on `urCommandBufferEnqueueExp` to execute **before** -*CB* contains a single command. This command is a barrier on *EL* that signals -*CB*'s *WaitEvent* when completed. - -The L0 command-list created on `urCommandBufferEnqueueExp` to execute **after** -*CB* also contains a single command. This command is a barrier on *CB*'s -*SignalEvent* that signals *RE* when completed. - #### Drawbacks -There are two drawbacks of this approach to implementing UR command-buffers for +There are three drawbacks of this approach to implementing UR command-buffers for Level Zero: 1. 3x the command-list resources are used, if there are many UR command-buffers in diff --git a/sycl/doc/design/images/L0_UR_command-buffer-v3.jpg b/sycl/doc/design/images/L0_UR_command-buffer-v3.jpg deleted file mode 100644 index 5b4ff1c3e9aabbf9e572b5c67efd080e337d6009..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61543 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

uoRo;MIR4JG<*>MEtR3Uu8MW^cBl=lDX=h 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 z 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 O0a1O*o4@V - # Date: Wed Feb 14 11:17:21 2024 +0100 - # Merge pull request #1216 from igchor/umf_standalone - # [UR] Remove UMF sources and use standalone UMF repo instead - set(UNIFIED_RUNTIME_TAG cfba9f160528018055881f1ccf9ab98ec59c963f) + set(UNIFIED_RUNTIME_REPO "https://github.com/bensuo/unified-runtime.git") + set(UNIFIED_RUNTIME_TAG maxime/optim-command-buffer-submission) if(SYCL_PI_UR_OVERRIDE_FETCH_CONTENT_REPO) set(UNIFIED_RUNTIME_REPO "${SYCL_PI_UR_OVERRIDE_FETCH_CONTENT_REPO}") From 8c5dea532d428601a065f9b78670aab9ecd0bbd1 Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Fri, 23 Feb 2024 16:33:07 +0000 Subject: [PATCH 02/14] [SYCL][Graph] Enable in-order cmd-list Analyze the graph and apply enable the use of in-order command-list for linear graph. Add a property to finalize function to disable this optimization which is not compatible with profiling. Update the specification. --- .../sycl_ext_oneapi_graph.asciidoc | 19 ++++++- sycl/include/sycl/detail/pi.h | 2 +- sycl/include/sycl/detail/property_helper.hpp | 3 +- .../sycl/ext/oneapi/experimental/graph.hpp | 13 ++++- sycl/plugins/unified_runtime/CMakeLists.txt | 11 ++-- sycl/plugins/unified_runtime/pi2ur.hpp | 7 +-- sycl/source/detail/graph_impl.cpp | 25 ++++++--- sycl/source/detail/graph_impl.hpp | 52 ++++++++++++++++++- sycl/test-e2e/Graph/event_profiling_info.cpp | 8 ++- 9 files changed, 114 insertions(+), 26 deletions(-) diff --git a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc index 1ad10bfbf2d1c..efe0d0821eddd 100644 --- a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc +++ b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc @@ -341,6 +341,11 @@ class assume_buffer_outlives_graph { public: assume_buffer_outlives_graph() = default; }; + +class disable_in_order_optimization { +public: + disable_in_order_optimization() = default; +}; } // namespace graph namespace node { @@ -646,6 +651,15 @@ which is used in a graph will be kept alive on the host for the lifetime of the graph. Destroying that buffer during the lifetime of a `command_graph` constructed with this property results in undefined behavior. +===== Disable-In-Order-Optimization Property [[disable-in-order-optimization]] + +The `property::graph::disable_in_order_optimization` property disables +an optimization which can be applied to in-order graph to +reduce its execution time. +This property is passed to the `command_graph::finalize()` function. +Note that this property must be passed to the finalize function if users +want to profile the exec_graph execution. + ==== Graph Member Functions Table {counter: tableNumber}. Constructor of the `command_graph` class. @@ -849,8 +863,9 @@ Preconditions: Parameters: -* `propList` - Optional parameter for passing properties. No finalization - properties are defined by this extension. +* `propList` - Optional parameter for passing properties. The only defined +property is `disable_in_order_optimization`. See <> +for more details. Returns: A new executable graph object which can be submitted to a queue. diff --git a/sycl/include/sycl/detail/pi.h b/sycl/include/sycl/detail/pi.h index 5059125da7646..91b52683e0ac4 100644 --- a/sycl/include/sycl/detail/pi.h +++ b/sycl/include/sycl/detail/pi.h @@ -2304,7 +2304,7 @@ typedef enum { struct pi_ext_command_buffer_desc final { pi_ext_structure_type stype; const void *pNext; - pi_queue_properties *properties; + pi_bool is_in_order; }; /// API to create a command-buffer. diff --git a/sycl/include/sycl/detail/property_helper.hpp b/sycl/include/sycl/detail/property_helper.hpp index 3009af8ee2890..bfbfeff8b846f 100644 --- a/sycl/include/sycl/detail/property_helper.hpp +++ b/sycl/include/sycl/detail/property_helper.hpp @@ -47,8 +47,9 @@ enum DataLessPropKind { GraphAssumeDataOutlivesBuffer = 22, GraphAssumeBufferOutlivesGraph = 23, GraphDependOnAllLeaves = 24, + DisableInOrderOptimization = 25, // Indicates the last known dataless property. - LastKnownDataLessPropKind = 24, + LastKnownDataLessPropKind = 25, // Exceeding 32 may cause ABI breaking change on some of OSes. DataLessPropKindSize = 32 }; diff --git a/sycl/include/sycl/ext/oneapi/experimental/graph.hpp b/sycl/include/sycl/ext/oneapi/experimental/graph.hpp index 209a0ed25f72f..9859e173b7339 100644 --- a/sycl/include/sycl/ext/oneapi/experimental/graph.hpp +++ b/sycl/include/sycl/ext/oneapi/experimental/graph.hpp @@ -146,6 +146,15 @@ class assume_buffer_outlives_graph public: assume_buffer_outlives_graph() = default; }; + +/// Property used to to add all previous graph leaves as dependencies when +/// creating a new node with command_graph::add(). +class disable_in_order_optimization + : public ::sycl::detail::DataLessProperty< + ::sycl::detail::DisableInOrderOptimization> { +public: + disable_in_order_optimization() = default; +}; } // namespace graph namespace node { @@ -340,8 +349,10 @@ class __SYCL_EXPORT executable_command_graph { /// Constructor used by internal runtime. /// @param Graph Detail implementation class to construct with. /// @param Ctx Context to use for graph. + /// @param DisableInOrderOptimization Disable the In Order graph opimization executable_command_graph(const std::shared_ptr &Graph, - const sycl::context &Ctx); + const sycl::context &Ctx, + const bool DisableInOrderOptimization = false); template friend decltype(Obj::impl) diff --git a/sycl/plugins/unified_runtime/CMakeLists.txt b/sycl/plugins/unified_runtime/CMakeLists.txt index 0ec7da85066f2..1adcaf4403e2d 100644 --- a/sycl/plugins/unified_runtime/CMakeLists.txt +++ b/sycl/plugins/unified_runtime/CMakeLists.txt @@ -56,14 +56,9 @@ endif() if(SYCL_PI_UR_USE_FETCH_CONTENT) include(FetchContent) - set(UNIFIED_RUNTIME_REPO "https://github.com/oneapi-src/unified-runtime.git") - # commit 3487672ceba0fd3575b5f3f15a832b100dc5fbad - # Author: Artur Gainullin - # Date: Fri Feb 16 09:59:50 2024 -0800 - # - # [UR] Provide flexibility to replace unified-memory-framework repo and tag - set(UNIFIED_RUNTIME_TAG 3487672ceba0fd3575b5f3f15a832b100dc5fbad) - + set(UNIFIED_RUNTIME_REPO "https://github.com/bensuo/unified-runtime.git") + set(UNIFIED_RUNTIME_TAG maxime/in-order-cmd-list) + if(SYCL_PI_UR_OVERRIDE_FETCH_CONTENT_REPO) set(UNIFIED_RUNTIME_REPO "${SYCL_PI_UR_OVERRIDE_FETCH_CONTENT_REPO}") endif() diff --git a/sycl/plugins/unified_runtime/pi2ur.hpp b/sycl/plugins/unified_runtime/pi2ur.hpp index e3a92022567d0..a17d7ebbe8503 100644 --- a/sycl/plugins/unified_runtime/pi2ur.hpp +++ b/sycl/plugins/unified_runtime/pi2ur.hpp @@ -4425,13 +4425,14 @@ piextCommandBufferCreate(pi_context Context, pi_device Device, ur_context_handle_t UrContext = reinterpret_cast(Context); ur_device_handle_t UrDevice = reinterpret_cast(Device); - const ur_exp_command_buffer_desc_t *UrDesc = - reinterpret_cast(Desc); + ur_exp_command_buffer_desc_t UrDesc; + UrDesc.stype = UR_STRUCTURE_TYPE_EXP_COMMAND_BUFFER_DESC; + UrDesc.isInOrder = Desc->is_in_order; ur_exp_command_buffer_handle_t *UrCommandBuffer = reinterpret_cast(RetCommandBuffer); HANDLE_ERRORS( - urCommandBufferCreateExp(UrContext, UrDevice, UrDesc, UrCommandBuffer)); + urCommandBufferCreateExp(UrContext, UrDevice, &UrDesc, UrCommandBuffer)); return PI_SUCCESS; } diff --git a/sycl/source/detail/graph_impl.cpp b/sycl/source/detail/graph_impl.cpp index 980ea7e3e9eba..e56c662040016 100644 --- a/sycl/source/detail/graph_impl.cpp +++ b/sycl/source/detail/graph_impl.cpp @@ -265,6 +265,7 @@ void exec_graph_impl::makePartitions() { } if (Partition->MRoots.size() > 0) { Partition->schedule(); + Partition->checkIfGraphIsSinglePath(); MPartitions.push_back(Partition); PartitionFinalNum++; } @@ -613,6 +614,8 @@ std::vector graph_impl::getExitNodesEvents() { void exec_graph_impl::findRealDeps( std::vector &Deps, std::shared_ptr CurrentNode, int ReferencePartitionNum) { + // if (MPartitions[MPartitionNodes[CurrentNode]]->MIsInOrderGraph) + // return; if (CurrentNode->isEmpty()) { for (auto &N : CurrentNode->MPredecessors) { auto NodeImpl = N.lock(); @@ -680,7 +683,9 @@ sycl::detail::pi::PiExtSyncPoint exec_graph_impl::enqueueNode( void exec_graph_impl::createCommandBuffers( sycl::device Device, std::shared_ptr &Partition) { sycl::detail::pi::PiExtCommandBuffer OutCommandBuffer; - sycl::detail::pi::PiExtCommandBufferDesc Desc{}; + sycl::detail::pi::PiExtCommandBufferDesc Desc{ + pi_ext_structure_type::PI_EXT_STRUCTURE_TYPE_COMMAND_BUFFER_DESC, nullptr, + pi_bool(Partition->MIsInOrderGraph & UseInOrderCommandList)}; auto ContextImpl = sycl::detail::getSyclObjImpl(MContext); const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin(); auto DeviceImpl = sycl::detail::getSyclObjImpl(Device); @@ -694,6 +699,8 @@ void exec_graph_impl::createCommandBuffers( Partition->MPiCommandBuffers[Device] = OutCommandBuffer; + printGraphAsDot("execgraph.dot", false); + for (const auto &Node : Partition->MSchedule) { // Empty nodes are not processed as other nodes, but only their // dependencies are propagated in findRealDeps @@ -1152,12 +1159,16 @@ void modifiable_command_graph::make_edge(node &Src, node &Dest) { } command_graph -modifiable_command_graph::finalize(const sycl::property_list &) const { +modifiable_command_graph::finalize(const sycl::property_list &PropList) const { // Graph is read and written in this scope so we lock // this graph with full priviledges. graph_impl::WriteLock Lock(impl->MMutex); - return command_graph{this->impl, - this->impl->getContext()}; + bool DisableInOrderOptim = false; + if (PropList.has_property()) { + DisableInOrderOptim = true; + } + return command_graph{ + this->impl, this->impl->getContext(), DisableInOrderOptim}; } bool modifiable_command_graph::begin_recording(queue &RecordingQueue) { @@ -1271,8 +1282,10 @@ std::vector modifiable_command_graph::get_root_nodes() const { } executable_command_graph::executable_command_graph( - const std::shared_ptr &Graph, const sycl::context &Ctx) - : impl(std::make_shared(Ctx, Graph)) { + const std::shared_ptr &Graph, const sycl::context &Ctx, + const bool DisableInOrderOptimization) + : impl(std::make_shared( + Ctx, Graph, DisableInOrderOptimization)) { finalizeImpl(); // Create backend representation for executable graph } diff --git a/sycl/source/detail/graph_impl.hpp b/sycl/source/detail/graph_impl.hpp index eafb66b1dca9b..75ace1c386da5 100644 --- a/sycl/source/detail/graph_impl.hpp +++ b/sycl/source/detail/graph_impl.hpp @@ -331,6 +331,24 @@ class node_impl { } } + /// Test is the node contains a N-D copy + /// @return true is the op is a N-D copy + bool is2DCopyNode() { + if ((MCGType == sycl::detail::CG::CGTYPE::CopyAccToAcc) || + (MCGType == sycl::detail::CG::CGTYPE::CopyAccToPtr) || + (MCGType == sycl::detail::CG::CGTYPE::CopyPtrToAcc)) { + sycl::detail::CGCopy *Copy = (sycl::detail::CGCopy *)MCommandGroup.get(); + sycl::detail::Requirement *ReqSrc = + (sycl::detail::Requirement *)(Copy->getSrc()); + sycl::detail::Requirement *ReqDst = + (sycl::detail::Requirement *)(Copy->getDst()); + if ((ReqSrc->MDims > 1) || (ReqDst->MDims > 1)) { + return true; + } + } + return false; + } + private: /// Prints Node information to Stream. /// @param Stream Where to print the Node information @@ -550,6 +568,9 @@ class partition { MPiCommandBuffers; /// List of predecessors to this partition. std::vector> MPredecessors; + /// True is the graph of this partition is a single path graph + /// and InOrder optmization can be applied on it. + bool MIsInOrderGraph = false; /// @return True if the partition contains a host task bool isHostTask() const { @@ -557,6 +578,27 @@ class partition { sycl::detail::CG::CGTYPE::CodeplayHostTask)); } + /// Checks if the graph is single path, i.e. each node has a single successor. + /// If so, the MIsInOrderGraph flag is set. + void checkIfGraphIsSinglePath() { + // Is the graph of this partition a single path graph? + // If so, we can optimize its execution using InOrder optimizations + MIsInOrderGraph = true; + if (MRoots.size() > 1) { + MIsInOrderGraph = false; + return; + } + for (auto Node : MSchedule) { + // In version 1.3.28454 of the L0 driver, 2D Copy ops cannot not + // be enqueued in an in-order cmd-list (causing execution to stall). + // The 2D Copy test should be removed from here when the bug is fixed. + if ((Node->MSuccessors.size() > 1) || (Node->is2DCopyNode())) { + MIsInOrderGraph = false; + return; + } + } + } + /// Add nodes to MSchedule. void schedule(); }; @@ -1021,10 +1063,14 @@ class exec_graph_impl { /// nodes). /// @param Context Context to create graph with. /// @param GraphImpl Modifiable graph implementation to create with. + /// @param DisableInOrderOptimization Disable the In Order Command-List + /// optimization exec_graph_impl(sycl::context Context, - const std::shared_ptr &GraphImpl) + const std::shared_ptr &GraphImpl, + const bool DisableInOrderOptimization = false) : MSchedule(), MGraphImpl(GraphImpl), MPiSyncPoints(), MContext(Context), - MRequirements(), MExecutionEvents() { + MRequirements(), MExecutionEvents(), + UseInOrderCommandList(!DisableInOrderOptimization) { // Copy nodes from GraphImpl and merge any subgraph nodes into this graph. duplicateNodes(); } @@ -1195,6 +1241,8 @@ class exec_graph_impl { MPartitionsExecutionEvents; /// Storage for copies of nodes from the original modifiable graph. std::vector> MNodeStorage; + /// If true, the L0 backend In-order CommandList optimization is enabled. + bool UseInOrderCommandList = true; }; } // namespace detail diff --git a/sycl/test-e2e/Graph/event_profiling_info.cpp b/sycl/test-e2e/Graph/event_profiling_info.cpp index c94117ea655ec..902388b6af62d 100644 --- a/sycl/test-e2e/Graph/event_profiling_info.cpp +++ b/sycl/test-e2e/Graph/event_profiling_info.cpp @@ -130,8 +130,12 @@ int main() { KernelGraph.end_recording(Queue); - auto CopyGraphExec = CopyGraph.finalize(); - auto KernelGraphExec = KernelGraph.finalize(); + // The profiling is not available with the In-Order optimization. + // We therefore disable this optimization. + auto CopyGraphExec = CopyGraph.finalize( + exp_ext::property::graph::disable_in_order_optimization{}); + auto KernelGraphExec = KernelGraph.finalize( + exp_ext::property::graph::disable_in_order_optimization{}); event CopyEvent, KernelEvent1, KernelEvent2; // Run graphs From f671539235b666b88c375f90a609d3c75013696b Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Mon, 26 Feb 2024 14:51:29 +0000 Subject: [PATCH 03/14] Add test for cehcking profiling when in-order command-list enabled --- sycl/test-e2e/Graph/event_profiling_info.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sycl/test-e2e/Graph/event_profiling_info.cpp b/sycl/test-e2e/Graph/event_profiling_info.cpp index 902388b6af62d..a7b2f3368d962 100644 --- a/sycl/test-e2e/Graph/event_profiling_info.cpp +++ b/sycl/test-e2e/Graph/event_profiling_info.cpp @@ -182,6 +182,25 @@ int main() { assert(verifyProfiling(CopyEvent) && verifyProfiling(KernelEvent1) && verifyProfiling(KernelEvent2) && compareProfiling(KernelEvent1, KernelEvent2)); + + // Checks exception thrown if profiling is requested while in-order + // optimization enabled. Note that in-order cmd-list optmization is only + // available for level-zero backend. + auto Backend = Dev.get_backend(); + if (Backend == backend::ext_oneapi_level_zero) { + auto CopyGraphExecInOrder = CopyGraph.finalize(); + auto EventInOrder = Queue.submit( + [&](handler &CGH) { CGH.ext_oneapi_graph(CopyGraphExecInOrder); }); + Queue.wait_and_throw(); + bool Success = false; + try { + EventInOrder + .get_profiling_info(); + } catch (sycl::exception &E) { + Success = true; + } + assert(Success); + } } host_accessor HostData(BufferTo); From 15f02c045eb9939f9addc843a2e20d87fc453044 Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Tue, 27 Feb 2024 10:44:40 +0000 Subject: [PATCH 04/14] Change property to `enable_profiling` + typo --- .../sycl_ext_oneapi_graph.asciidoc | 16 ++++++++-------- sycl/include/sycl/detail/property_helper.hpp | 2 +- .../sycl/ext/oneapi/experimental/graph.hpp | 11 +++++------ sycl/source/detail/graph_impl.cpp | 18 +++++++----------- sycl/source/detail/graph_impl.hpp | 11 +++++------ sycl/test-e2e/Graph/event_profiling_info.cpp | 8 ++++---- 6 files changed, 30 insertions(+), 36 deletions(-) diff --git a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc index efe0d0821eddd..a25dd521e2566 100644 --- a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc +++ b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc @@ -342,9 +342,8 @@ class assume_buffer_outlives_graph { assume_buffer_outlives_graph() = default; }; -class disable_in_order_optimization { public: - disable_in_order_optimization() = default; + enable_profiling() = default; }; } // namespace graph @@ -651,14 +650,15 @@ which is used in a graph will be kept alive on the host for the lifetime of the graph. Destroying that buffer during the lifetime of a `command_graph` constructed with this property results in undefined behavior. -===== Disable-In-Order-Optimization Property [[disable-in-order-optimization]] +===== Enable-Profiling Property [[enable-profiling]] -The `property::graph::disable_in_order_optimization` property disables -an optimization which can be applied to in-order graph to -reduce its execution time. +The `property::graph::enable_profiling` property enable profiling +the executable_graph. This property is passed to the `command_graph::finalize()` function. -Note that this property must be passed to the finalize function if users -want to profile the exec_graph execution. +If this property is not passed to the finalize function, certain optimizations, +which prevent graph profiling, may be applied to this executable graph. +In this case, an error will be thrown when attempting to profiling an event from +a graph submission that was created without this property. ==== Graph Member Functions diff --git a/sycl/include/sycl/detail/property_helper.hpp b/sycl/include/sycl/detail/property_helper.hpp index bfbfeff8b846f..7743f1e5a370a 100644 --- a/sycl/include/sycl/detail/property_helper.hpp +++ b/sycl/include/sycl/detail/property_helper.hpp @@ -47,7 +47,7 @@ enum DataLessPropKind { GraphAssumeDataOutlivesBuffer = 22, GraphAssumeBufferOutlivesGraph = 23, GraphDependOnAllLeaves = 24, - DisableInOrderOptimization = 25, + GraphEnableProfiling = 25, // Indicates the last known dataless property. LastKnownDataLessPropKind = 25, // Exceeding 32 may cause ABI breaking change on some of OSes. diff --git a/sycl/include/sycl/ext/oneapi/experimental/graph.hpp b/sycl/include/sycl/ext/oneapi/experimental/graph.hpp index 9859e173b7339..84c4c66a36ece 100644 --- a/sycl/include/sycl/ext/oneapi/experimental/graph.hpp +++ b/sycl/include/sycl/ext/oneapi/experimental/graph.hpp @@ -149,11 +149,10 @@ class assume_buffer_outlives_graph /// Property used to to add all previous graph leaves as dependencies when /// creating a new node with command_graph::add(). -class disable_in_order_optimization - : public ::sycl::detail::DataLessProperty< - ::sycl::detail::DisableInOrderOptimization> { +class enable_profiling : public ::sycl::detail::DataLessProperty< + ::sycl::detail::GraphEnableProfiling> { public: - disable_in_order_optimization() = default; + enable_profiling() = default; }; } // namespace graph @@ -349,10 +348,10 @@ class __SYCL_EXPORT executable_command_graph { /// Constructor used by internal runtime. /// @param Graph Detail implementation class to construct with. /// @param Ctx Context to use for graph. - /// @param DisableInOrderOptimization Disable the In Order graph opimization + /// @param EnableProfiling Enable graph profiling. executable_command_graph(const std::shared_ptr &Graph, const sycl::context &Ctx, - const bool DisableInOrderOptimization = false); + const bool EnableProfiling = false); template friend decltype(Obj::impl) diff --git a/sycl/source/detail/graph_impl.cpp b/sycl/source/detail/graph_impl.cpp index e56c662040016..33310decf35be 100644 --- a/sycl/source/detail/graph_impl.cpp +++ b/sycl/source/detail/graph_impl.cpp @@ -614,8 +614,6 @@ std::vector graph_impl::getExitNodesEvents() { void exec_graph_impl::findRealDeps( std::vector &Deps, std::shared_ptr CurrentNode, int ReferencePartitionNum) { - // if (MPartitions[MPartitionNodes[CurrentNode]]->MIsInOrderGraph) - // return; if (CurrentNode->isEmpty()) { for (auto &N : CurrentNode->MPredecessors) { auto NodeImpl = N.lock(); @@ -699,8 +697,6 @@ void exec_graph_impl::createCommandBuffers( Partition->MPiCommandBuffers[Device] = OutCommandBuffer; - printGraphAsDot("execgraph.dot", false); - for (const auto &Node : Partition->MSchedule) { // Empty nodes are not processed as other nodes, but only their // dependencies are propagated in findRealDeps @@ -1163,12 +1159,12 @@ modifiable_command_graph::finalize(const sycl::property_list &PropList) const { // Graph is read and written in this scope so we lock // this graph with full priviledges. graph_impl::WriteLock Lock(impl->MMutex); - bool DisableInOrderOptim = false; - if (PropList.has_property()) { - DisableInOrderOptim = true; + bool EnableProfiling = false; + if (PropList.has_property()) { + EnableProfiling = true; } return command_graph{ - this->impl, this->impl->getContext(), DisableInOrderOptim}; + this->impl, this->impl->getContext(), EnableProfiling}; } bool modifiable_command_graph::begin_recording(queue &RecordingQueue) { @@ -1283,9 +1279,9 @@ std::vector modifiable_command_graph::get_root_nodes() const { executable_command_graph::executable_command_graph( const std::shared_ptr &Graph, const sycl::context &Ctx, - const bool DisableInOrderOptimization) - : impl(std::make_shared( - Ctx, Graph, DisableInOrderOptimization)) { + const bool EnableProfiling) + : impl(std::make_shared(Ctx, Graph, + EnableProfiling)) { finalizeImpl(); // Create backend representation for executable graph } diff --git a/sycl/source/detail/graph_impl.hpp b/sycl/source/detail/graph_impl.hpp index 75ace1c386da5..a0271fcff8e7b 100644 --- a/sycl/source/detail/graph_impl.hpp +++ b/sycl/source/detail/graph_impl.hpp @@ -333,7 +333,7 @@ class node_impl { /// Test is the node contains a N-D copy /// @return true is the op is a N-D copy - bool is2DCopyNode() { + bool is2DCopyNode() const { if ((MCGType == sycl::detail::CG::CGTYPE::CopyAccToAcc) || (MCGType == sycl::detail::CG::CGTYPE::CopyAccToPtr) || (MCGType == sycl::detail::CG::CGTYPE::CopyPtrToAcc)) { @@ -588,7 +588,7 @@ class partition { MIsInOrderGraph = false; return; } - for (auto Node : MSchedule) { + for (const auto &Node : MSchedule) { // In version 1.3.28454 of the L0 driver, 2D Copy ops cannot not // be enqueued in an in-order cmd-list (causing execution to stall). // The 2D Copy test should be removed from here when the bug is fixed. @@ -1063,14 +1063,13 @@ class exec_graph_impl { /// nodes). /// @param Context Context to create graph with. /// @param GraphImpl Modifiable graph implementation to create with. - /// @param DisableInOrderOptimization Disable the In Order Command-List - /// optimization + /// @param EnableProfiling Enable graph profiling. exec_graph_impl(sycl::context Context, const std::shared_ptr &GraphImpl, - const bool DisableInOrderOptimization = false) + const bool EnableProfiling = false) : MSchedule(), MGraphImpl(GraphImpl), MPiSyncPoints(), MContext(Context), MRequirements(), MExecutionEvents(), - UseInOrderCommandList(!DisableInOrderOptimization) { + UseInOrderCommandList(!EnableProfiling) { // Copy nodes from GraphImpl and merge any subgraph nodes into this graph. duplicateNodes(); } diff --git a/sycl/test-e2e/Graph/event_profiling_info.cpp b/sycl/test-e2e/Graph/event_profiling_info.cpp index a7b2f3368d962..3ad2ac28c48ad 100644 --- a/sycl/test-e2e/Graph/event_profiling_info.cpp +++ b/sycl/test-e2e/Graph/event_profiling_info.cpp @@ -132,10 +132,10 @@ int main() { // The profiling is not available with the In-Order optimization. // We therefore disable this optimization. - auto CopyGraphExec = CopyGraph.finalize( - exp_ext::property::graph::disable_in_order_optimization{}); - auto KernelGraphExec = KernelGraph.finalize( - exp_ext::property::graph::disable_in_order_optimization{}); + auto CopyGraphExec = + CopyGraph.finalize(exp_ext::property::graph::enable_profiling{}); + auto KernelGraphExec = + KernelGraph.finalize(exp_ext::property::graph::enable_profiling{}); event CopyEvent, KernelEvent1, KernelEvent2; // Run graphs From 0527464a0f6b6da4c4446097abb14cfa68d275da Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Tue, 27 Feb 2024 16:43:29 +0000 Subject: [PATCH 05/14] Propagate enableProfiling property to UR. --- sycl/include/sycl/detail/pi.h | 1 + sycl/plugins/unified_runtime/pi2ur.hpp | 1 + sycl/source/detail/graph_impl.cpp | 3 ++- sycl/source/detail/graph_impl.hpp | 7 +++++-- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/sycl/include/sycl/detail/pi.h b/sycl/include/sycl/detail/pi.h index 91b52683e0ac4..a3d28f1de9ae4 100644 --- a/sycl/include/sycl/detail/pi.h +++ b/sycl/include/sycl/detail/pi.h @@ -2305,6 +2305,7 @@ struct pi_ext_command_buffer_desc final { pi_ext_structure_type stype; const void *pNext; pi_bool is_in_order; + pi_bool enable_profiling; }; /// API to create a command-buffer. diff --git a/sycl/plugins/unified_runtime/pi2ur.hpp b/sycl/plugins/unified_runtime/pi2ur.hpp index a17d7ebbe8503..03d4166e20c7e 100644 --- a/sycl/plugins/unified_runtime/pi2ur.hpp +++ b/sycl/plugins/unified_runtime/pi2ur.hpp @@ -4428,6 +4428,7 @@ piextCommandBufferCreate(pi_context Context, pi_device Device, ur_exp_command_buffer_desc_t UrDesc; UrDesc.stype = UR_STRUCTURE_TYPE_EXP_COMMAND_BUFFER_DESC; UrDesc.isInOrder = Desc->is_in_order; + UrDesc.enableProfiling = Desc->enable_profiling; ur_exp_command_buffer_handle_t *UrCommandBuffer = reinterpret_cast(RetCommandBuffer); diff --git a/sycl/source/detail/graph_impl.cpp b/sycl/source/detail/graph_impl.cpp index 33310decf35be..a868deafd1047 100644 --- a/sycl/source/detail/graph_impl.cpp +++ b/sycl/source/detail/graph_impl.cpp @@ -683,7 +683,8 @@ void exec_graph_impl::createCommandBuffers( sycl::detail::pi::PiExtCommandBuffer OutCommandBuffer; sycl::detail::pi::PiExtCommandBufferDesc Desc{ pi_ext_structure_type::PI_EXT_STRUCTURE_TYPE_COMMAND_BUFFER_DESC, nullptr, - pi_bool(Partition->MIsInOrderGraph & UseInOrderCommandList)}; + pi_bool(Partition->MIsInOrderGraph & MUseInOrderCommandList), + pi_bool(MEnableProfiling)}; auto ContextImpl = sycl::detail::getSyclObjImpl(MContext); const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin(); auto DeviceImpl = sycl::detail::getSyclObjImpl(Device); diff --git a/sycl/source/detail/graph_impl.hpp b/sycl/source/detail/graph_impl.hpp index a0271fcff8e7b..b9e8d997b17c8 100644 --- a/sycl/source/detail/graph_impl.hpp +++ b/sycl/source/detail/graph_impl.hpp @@ -1069,7 +1069,8 @@ class exec_graph_impl { const bool EnableProfiling = false) : MSchedule(), MGraphImpl(GraphImpl), MPiSyncPoints(), MContext(Context), MRequirements(), MExecutionEvents(), - UseInOrderCommandList(!EnableProfiling) { + MUseInOrderCommandList(!EnableProfiling), + MEnableProfiling(EnableProfiling) { // Copy nodes from GraphImpl and merge any subgraph nodes into this graph. duplicateNodes(); } @@ -1241,7 +1242,9 @@ class exec_graph_impl { /// Storage for copies of nodes from the original modifiable graph. std::vector> MNodeStorage; /// If true, the L0 backend In-order CommandList optimization is enabled. - bool UseInOrderCommandList = true; + bool MUseInOrderCommandList = true; + /// If true, the graph profiling is enabled. + bool MEnableProfiling = false; }; } // namespace detail From b55a301f329a833fc03ebcc35c6930c8ff9bb95a Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Tue, 27 Feb 2024 17:16:36 +0000 Subject: [PATCH 06/14] Update spec --- sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc index a25dd521e2566..63b9985789953 100644 --- a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc +++ b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc @@ -659,6 +659,7 @@ If this property is not passed to the finalize function, certain optimizations, which prevent graph profiling, may be applied to this executable graph. In this case, an error will be thrown when attempting to profiling an event from a graph submission that was created without this property. +Note that this limitation currently only applies to the zero-level backend. ==== Graph Member Functions From d885aa0c5c603ff509bcc209481029ad753e66b6 Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Wed, 28 Feb 2024 09:54:02 +0000 Subject: [PATCH 07/14] Update sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc Co-authored-by: Pablo Reble --- .../extensions/experimental/sycl_ext_oneapi_graph.asciidoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc index 63b9985789953..b4ad2c887186e 100644 --- a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc +++ b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc @@ -652,9 +652,9 @@ constructed with this property results in undefined behavior. ===== Enable-Profiling Property [[enable-profiling]] -The `property::graph::enable_profiling` property enable profiling -the executable_graph. -This property is passed to the `command_graph::finalize()` function. +The `property::graph::enable_profiling` property can be passed to the +`command_graph::finalize()` function and enables profiling support +for the returned `command_graph`. If this property is not passed to the finalize function, certain optimizations, which prevent graph profiling, may be applied to this executable graph. In this case, an error will be thrown when attempting to profiling an event from From b922a77d3cf96d52cf2be0c2b386a4c684d38166 Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Wed, 28 Feb 2024 10:38:23 +0000 Subject: [PATCH 08/14] Add exception throwing for all backends if enable_profiling property is not passed to finalize(). + Update spec. --- .../sycl_ext_oneapi_graph.asciidoc | 13 ++++---- .../sycl/ext/oneapi/experimental/graph.hpp | 5 ++-- sycl/source/detail/event_impl.hpp | 4 ++- sycl/source/detail/graph_impl.cpp | 5 +++- sycl/source/detail/graph_impl.hpp | 6 +--- sycl/test-e2e/Graph/event_profiling_info.cpp | 30 ++++++++----------- 6 files changed, 31 insertions(+), 32 deletions(-) diff --git a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc index b4ad2c887186e..d2b43e545d771 100644 --- a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc +++ b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc @@ -655,11 +655,12 @@ constructed with this property results in undefined behavior. The `property::graph::enable_profiling` property can be passed to the `command_graph::finalize()` function and enables profiling support for the returned `command_graph`. -If this property is not passed to the finalize function, certain optimizations, -which prevent graph profiling, may be applied to this executable graph. -In this case, an error will be thrown when attempting to profiling an event from -a graph submission that was created without this property. -Note that this limitation currently only applies to the zero-level backend. +Passing this property to the finalize function implies disabling +certain optimizations to enable graph profiling. +As a result, the execution time of a graph finalized with profiling enabled +is longer than that of a graph without profiling capability. +In this case, an error will be thrown when attempting to profiling an event +from a graph submission that was created without this property. ==== Graph Member Functions @@ -865,7 +866,7 @@ Preconditions: Parameters: * `propList` - Optional parameter for passing properties. The only defined -property is `disable_in_order_optimization`. See <> +property is `enable_profiling`. See <> for more details. Returns: A new executable graph object which can be submitted to a queue. diff --git a/sycl/include/sycl/ext/oneapi/experimental/graph.hpp b/sycl/include/sycl/ext/oneapi/experimental/graph.hpp index 84c4c66a36ece..029f68a032ba4 100644 --- a/sycl/include/sycl/ext/oneapi/experimental/graph.hpp +++ b/sycl/include/sycl/ext/oneapi/experimental/graph.hpp @@ -147,8 +147,9 @@ class assume_buffer_outlives_graph assume_buffer_outlives_graph() = default; }; -/// Property used to to add all previous graph leaves as dependencies when -/// creating a new node with command_graph::add(). +/// Property used to enable graph profiling. +/// Passing this property to the `command_graph::finalize()` function +/// ensures that profiling can be used on the generated graph. class enable_profiling : public ::sycl::detail::DataLessProperty< ::sycl::detail::GraphEnableProfiling> { public: diff --git a/sycl/source/detail/event_impl.hpp b/sycl/source/detail/event_impl.hpp index feb65cfc88946..e80b81d73b9ac 100644 --- a/sycl/source/detail/event_impl.hpp +++ b/sycl/source/detail/event_impl.hpp @@ -290,6 +290,8 @@ class event_impl { return MEventFromSubmittedExecCommandBuffer; } + void setProfilingEnabled(bool Value) { MIsProfilingEnabled = Value; } + protected: // When instrumentation is enabled emits trace event for event wait begin and // returns the telemetry event generated for the wait @@ -313,7 +315,7 @@ class event_impl { std::unique_ptr MHostProfilingInfo; void *MCommand = nullptr; std::weak_ptr MQueue; - const bool MIsProfilingEnabled = false; + bool MIsProfilingEnabled = false; const bool MFallbackProfiling = false; std::weak_ptr MWorkerQueue; diff --git a/sycl/source/detail/graph_impl.cpp b/sycl/source/detail/graph_impl.cpp index a868deafd1047..83205fb36382e 100644 --- a/sycl/source/detail/graph_impl.cpp +++ b/sycl/source/detail/graph_impl.cpp @@ -683,7 +683,7 @@ void exec_graph_impl::createCommandBuffers( sycl::detail::pi::PiExtCommandBuffer OutCommandBuffer; sycl::detail::pi::PiExtCommandBufferDesc Desc{ pi_ext_structure_type::PI_EXT_STRUCTURE_TYPE_COMMAND_BUFFER_DESC, nullptr, - pi_bool(Partition->MIsInOrderGraph & MUseInOrderCommandList), + pi_bool(Partition->MIsInOrderGraph & !MEnableProfiling), pi_bool(MEnableProfiling)}; auto ContextImpl = sycl::detail::getSyclObjImpl(MContext); const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin(); @@ -946,6 +946,9 @@ exec_graph_impl::enqueue(const std::shared_ptr &Queue, NewEvent->attachEventToComplete(Elem.second); } } + if (!MEnableProfiling) { + NewEvent->setProfilingEnabled(false); + } sycl::event QueueEvent = sycl::detail::createSyclObjFromImpl(NewEvent); return QueueEvent; diff --git a/sycl/source/detail/graph_impl.hpp b/sycl/source/detail/graph_impl.hpp index b9e8d997b17c8..ecd22ef830000 100644 --- a/sycl/source/detail/graph_impl.hpp +++ b/sycl/source/detail/graph_impl.hpp @@ -1068,9 +1068,7 @@ class exec_graph_impl { const std::shared_ptr &GraphImpl, const bool EnableProfiling = false) : MSchedule(), MGraphImpl(GraphImpl), MPiSyncPoints(), MContext(Context), - MRequirements(), MExecutionEvents(), - MUseInOrderCommandList(!EnableProfiling), - MEnableProfiling(EnableProfiling) { + MRequirements(), MExecutionEvents(), MEnableProfiling(EnableProfiling) { // Copy nodes from GraphImpl and merge any subgraph nodes into this graph. duplicateNodes(); } @@ -1241,8 +1239,6 @@ class exec_graph_impl { MPartitionsExecutionEvents; /// Storage for copies of nodes from the original modifiable graph. std::vector> MNodeStorage; - /// If true, the L0 backend In-order CommandList optimization is enabled. - bool MUseInOrderCommandList = true; /// If true, the graph profiling is enabled. bool MEnableProfiling = false; }; diff --git a/sycl/test-e2e/Graph/event_profiling_info.cpp b/sycl/test-e2e/Graph/event_profiling_info.cpp index 3ad2ac28c48ad..b875f489b681b 100644 --- a/sycl/test-e2e/Graph/event_profiling_info.cpp +++ b/sycl/test-e2e/Graph/event_profiling_info.cpp @@ -183,24 +183,20 @@ int main() { verifyProfiling(KernelEvent2) && compareProfiling(KernelEvent1, KernelEvent2)); - // Checks exception thrown if profiling is requested while in-order - // optimization enabled. Note that in-order cmd-list optmization is only - // available for level-zero backend. - auto Backend = Dev.get_backend(); - if (Backend == backend::ext_oneapi_level_zero) { - auto CopyGraphExecInOrder = CopyGraph.finalize(); - auto EventInOrder = Queue.submit( - [&](handler &CGH) { CGH.ext_oneapi_graph(CopyGraphExecInOrder); }); - Queue.wait_and_throw(); - bool Success = false; - try { - EventInOrder - .get_profiling_info(); - } catch (sycl::exception &E) { - Success = true; - } - assert(Success); + // Checks exception thrown if profiling is requested while the + // enable_profiling property has not been passed to `finalize()`. + auto CopyGraphExecInOrder = CopyGraph.finalize(); + auto EventInOrder = Queue.submit( + [&](handler &CGH) { CGH.ext_oneapi_graph(CopyGraphExecInOrder); }); + Queue.wait_and_throw(); + bool Success = false; + try { + EventInOrder + .get_profiling_info(); + } catch (sycl::exception &E) { + Success = true; } + assert(Success); } host_accessor HostData(BufferTo); From c084e19f8a266b096121df839348c6e9056144ad Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Wed, 28 Feb 2024 12:06:28 +0000 Subject: [PATCH 09/14] Typos --- sycl/source/detail/graph_impl.hpp | 10 ++++------ sycl/test-e2e/Graph/event_profiling_info.cpp | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/sycl/source/detail/graph_impl.hpp b/sycl/source/detail/graph_impl.hpp index ecd22ef830000..d47113a9010c4 100644 --- a/sycl/source/detail/graph_impl.hpp +++ b/sycl/source/detail/graph_impl.hpp @@ -331,9 +331,9 @@ class node_impl { } } - /// Test is the node contains a N-D copy - /// @return true is the op is a N-D copy - bool is2DCopyNode() const { + /// Test if the node contains a N-D copy + /// @return true if the op is a N-D copy + bool isNDCopyNode() const { if ((MCGType == sycl::detail::CG::CGTYPE::CopyAccToAcc) || (MCGType == sycl::detail::CG::CGTYPE::CopyAccToPtr) || (MCGType == sycl::detail::CG::CGTYPE::CopyPtrToAcc)) { @@ -581,8 +581,6 @@ class partition { /// Checks if the graph is single path, i.e. each node has a single successor. /// If so, the MIsInOrderGraph flag is set. void checkIfGraphIsSinglePath() { - // Is the graph of this partition a single path graph? - // If so, we can optimize its execution using InOrder optimizations MIsInOrderGraph = true; if (MRoots.size() > 1) { MIsInOrderGraph = false; @@ -592,7 +590,7 @@ class partition { // In version 1.3.28454 of the L0 driver, 2D Copy ops cannot not // be enqueued in an in-order cmd-list (causing execution to stall). // The 2D Copy test should be removed from here when the bug is fixed. - if ((Node->MSuccessors.size() > 1) || (Node->is2DCopyNode())) { + if ((Node->MSuccessors.size() > 1) || (Node->isNDCopyNode())) { MIsInOrderGraph = false; return; } diff --git a/sycl/test-e2e/Graph/event_profiling_info.cpp b/sycl/test-e2e/Graph/event_profiling_info.cpp index b875f489b681b..9e14aaa6028b3 100644 --- a/sycl/test-e2e/Graph/event_profiling_info.cpp +++ b/sycl/test-e2e/Graph/event_profiling_info.cpp @@ -130,7 +130,7 @@ int main() { KernelGraph.end_recording(Queue); - // The profiling is not available with the In-Order optimization. + // The profiling is not available with the in-order optimization. // We therefore disable this optimization. auto CopyGraphExec = CopyGraph.finalize(exp_ext::property::graph::enable_profiling{}); From 49630d8d7fb94379de5d25d3a21c72149d3c5971 Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Thu, 29 Feb 2024 11:03:31 +0000 Subject: [PATCH 10/14] Update sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc Co-authored-by: Ewan Crawford --- sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc index d2b43e545d771..59810dcecc309 100644 --- a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc +++ b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc @@ -659,7 +659,7 @@ Passing this property to the finalize function implies disabling certain optimizations to enable graph profiling. As a result, the execution time of a graph finalized with profiling enabled is longer than that of a graph without profiling capability. -In this case, an error will be thrown when attempting to profiling an event +An error will be thrown when attempting to profile an event from a graph submission that was created without this property. ==== Graph Member Functions From e4ee57ea107c7a3e6b618754c9ea5dc387acd2f6 Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Thu, 29 Feb 2024 12:42:22 +0000 Subject: [PATCH 11/14] Move test to unitest + typo --- .../sycl_ext_oneapi_graph.asciidoc | 5 ++-- sycl/test-e2e/Graph/event_profiling_info.cpp | 15 ---------- sycl/unittests/Extensions/CommandGraph.cpp | 28 +++++++++++++++++++ 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc index 59810dcecc309..8fdd202aa8efb 100644 --- a/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc +++ b/sycl/doc/extensions/experimental/sycl_ext_oneapi_graph.asciidoc @@ -342,8 +342,9 @@ class assume_buffer_outlives_graph { assume_buffer_outlives_graph() = default; }; -public: - enable_profiling() = default; +class enable_profiling { + public: + enable_profiling() = default; }; } // namespace graph diff --git a/sycl/test-e2e/Graph/event_profiling_info.cpp b/sycl/test-e2e/Graph/event_profiling_info.cpp index 9e14aaa6028b3..28ad32bf4ed79 100644 --- a/sycl/test-e2e/Graph/event_profiling_info.cpp +++ b/sycl/test-e2e/Graph/event_profiling_info.cpp @@ -182,21 +182,6 @@ int main() { assert(verifyProfiling(CopyEvent) && verifyProfiling(KernelEvent1) && verifyProfiling(KernelEvent2) && compareProfiling(KernelEvent1, KernelEvent2)); - - // Checks exception thrown if profiling is requested while the - // enable_profiling property has not been passed to `finalize()`. - auto CopyGraphExecInOrder = CopyGraph.finalize(); - auto EventInOrder = Queue.submit( - [&](handler &CGH) { CGH.ext_oneapi_graph(CopyGraphExecInOrder); }); - Queue.wait_and_throw(); - bool Success = false; - try { - EventInOrder - .get_profiling_info(); - } catch (sycl::exception &E) { - Success = true; - } - assert(Success); } host_accessor HostData(BufferTo); diff --git a/sycl/unittests/Extensions/CommandGraph.cpp b/sycl/unittests/Extensions/CommandGraph.cpp index 5ece9b1391baf..0382b73f6ee62 100644 --- a/sycl/unittests/Extensions/CommandGraph.cpp +++ b/sycl/unittests/Extensions/CommandGraph.cpp @@ -2265,6 +2265,34 @@ TEST_F(CommandGraphTest, ProfilingException) { } } +TEST_F(CommandGraphTest, ProfilingExceptionProperty) { + Graph.begin_recording(Queue); + auto Event1 = Queue.submit( + [&](sycl::handler &cgh) { cgh.single_task>([]() {}); }); + Graph.end_recording(Queue); + + // Checks exception thrown if profiling is requested while the + // enable_profiling property has not been passed to `finalize()`. + auto GraphExecInOrder = Graph.finalize(); + queue QueueProfile{Dev, {sycl::property::queue::enable_profiling()}}; + auto EventInOrder = QueueProfile.submit( + [&](handler &CGH) { CGH.ext_oneapi_graph(GraphExecInOrder); }); + QueueProfile.wait_and_throw(); + bool Success = true; + try { + EventInOrder + .get_profiling_info(); + } catch (sycl::exception &Exception) { + ASSERT_FALSE(std::string(Exception.what()) + .find("Profiling information is unavailable as the queue " + "associated with the event does not have the " + "'enable_profiling' property.") == + std::string::npos); + Success = false; + } + ASSERT_EQ(Success, false); +} + class MultiThreadGraphTest : public CommandGraphTest { public: MultiThreadGraphTest() From 0318696128e6962b1fb05e950eb904955cab49bb Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Wed, 6 Mar 2024 14:26:30 +0000 Subject: [PATCH 12/14] Pass prop-list to `executable_command_graph` constructor + typos --- sycl/include/sycl/ext/oneapi/experimental/graph.hpp | 5 +++-- sycl/source/detail/graph_impl.cpp | 13 ++++--------- sycl/source/detail/graph_impl.hpp | 12 +++++++----- sycl/test-e2e/Graph/event_profiling_info.cpp | 4 ++-- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/sycl/include/sycl/ext/oneapi/experimental/graph.hpp b/sycl/include/sycl/ext/oneapi/experimental/graph.hpp index 029f68a032ba4..1ffbf3c6d83c3 100644 --- a/sycl/include/sycl/ext/oneapi/experimental/graph.hpp +++ b/sycl/include/sycl/ext/oneapi/experimental/graph.hpp @@ -349,10 +349,11 @@ class __SYCL_EXPORT executable_command_graph { /// Constructor used by internal runtime. /// @param Graph Detail implementation class to construct with. /// @param Ctx Context to use for graph. - /// @param EnableProfiling Enable graph profiling. + /// @param PropList Optional list of properties to pass. executable_command_graph(const std::shared_ptr &Graph, const sycl::context &Ctx, - const bool EnableProfiling = false); + const property_list &PropList = {}); + template friend decltype(Obj::impl) diff --git a/sycl/source/detail/graph_impl.cpp b/sycl/source/detail/graph_impl.cpp index 83205fb36382e..a7a9d0c40a5f7 100644 --- a/sycl/source/detail/graph_impl.cpp +++ b/sycl/source/detail/graph_impl.cpp @@ -683,7 +683,7 @@ void exec_graph_impl::createCommandBuffers( sycl::detail::pi::PiExtCommandBuffer OutCommandBuffer; sycl::detail::pi::PiExtCommandBufferDesc Desc{ pi_ext_structure_type::PI_EXT_STRUCTURE_TYPE_COMMAND_BUFFER_DESC, nullptr, - pi_bool(Partition->MIsInOrderGraph & !MEnableProfiling), + pi_bool(Partition->MIsInOrderGraph && !MEnableProfiling), pi_bool(MEnableProfiling)}; auto ContextImpl = sycl::detail::getSyclObjImpl(MContext); const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin(); @@ -1163,12 +1163,8 @@ modifiable_command_graph::finalize(const sycl::property_list &PropList) const { // Graph is read and written in this scope so we lock // this graph with full priviledges. graph_impl::WriteLock Lock(impl->MMutex); - bool EnableProfiling = false; - if (PropList.has_property()) { - EnableProfiling = true; - } return command_graph{ - this->impl, this->impl->getContext(), EnableProfiling}; + this->impl, this->impl->getContext(), PropList}; } bool modifiable_command_graph::begin_recording(queue &RecordingQueue) { @@ -1283,9 +1279,8 @@ std::vector modifiable_command_graph::get_root_nodes() const { executable_command_graph::executable_command_graph( const std::shared_ptr &Graph, const sycl::context &Ctx, - const bool EnableProfiling) - : impl(std::make_shared(Ctx, Graph, - EnableProfiling)) { + const property_list &PropList) + : impl(std::make_shared(Ctx, Graph, PropList)) { finalizeImpl(); // Create backend representation for executable graph } diff --git a/sycl/source/detail/graph_impl.hpp b/sycl/source/detail/graph_impl.hpp index d47113a9010c4..64e86a9bf44fc 100644 --- a/sycl/source/detail/graph_impl.hpp +++ b/sycl/source/detail/graph_impl.hpp @@ -568,8 +568,8 @@ class partition { MPiCommandBuffers; /// List of predecessors to this partition. std::vector> MPredecessors; - /// True is the graph of this partition is a single path graph - /// and InOrder optmization can be applied on it. + /// True if the graph of this partition is a single path graph + /// and in-order optmization can be applied on it. bool MIsInOrderGraph = false; /// @return True if the partition contains a host task @@ -1061,12 +1061,14 @@ class exec_graph_impl { /// nodes). /// @param Context Context to create graph with. /// @param GraphImpl Modifiable graph implementation to create with. - /// @param EnableProfiling Enable graph profiling. + /// @param PropList List of properties for constructing this object. exec_graph_impl(sycl::context Context, const std::shared_ptr &GraphImpl, - const bool EnableProfiling = false) + const property_list &PropList) : MSchedule(), MGraphImpl(GraphImpl), MPiSyncPoints(), MContext(Context), - MRequirements(), MExecutionEvents(), MEnableProfiling(EnableProfiling) { + MRequirements(), MExecutionEvents(), + MEnableProfiling( + PropList.has_property()) { // Copy nodes from GraphImpl and merge any subgraph nodes into this graph. duplicateNodes(); } diff --git a/sycl/test-e2e/Graph/event_profiling_info.cpp b/sycl/test-e2e/Graph/event_profiling_info.cpp index 28ad32bf4ed79..24fc478223caa 100644 --- a/sycl/test-e2e/Graph/event_profiling_info.cpp +++ b/sycl/test-e2e/Graph/event_profiling_info.cpp @@ -130,8 +130,8 @@ int main() { KernelGraph.end_recording(Queue); - // The profiling is not available with the in-order optimization. - // We therefore disable this optimization. + // The `enable_profiling` property must be passed to the finalize function + // in order to query profiling information. auto CopyGraphExec = CopyGraph.finalize(exp_ext::property::graph::enable_profiling{}); auto KernelGraphExec = From b233136e3749bb1eedfe6c2a9cb89b3c9e79337b Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Wed, 6 Mar 2024 15:10:12 +0000 Subject: [PATCH 13/14] Update UR tag --- sycl/plugins/unified_runtime/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sycl/plugins/unified_runtime/CMakeLists.txt b/sycl/plugins/unified_runtime/CMakeLists.txt index 1adcaf4403e2d..29e4dfb13127f 100644 --- a/sycl/plugins/unified_runtime/CMakeLists.txt +++ b/sycl/plugins/unified_runtime/CMakeLists.txt @@ -57,7 +57,7 @@ if(SYCL_PI_UR_USE_FETCH_CONTENT) include(FetchContent) set(UNIFIED_RUNTIME_REPO "https://github.com/bensuo/unified-runtime.git") - set(UNIFIED_RUNTIME_TAG maxime/in-order-cmd-list) + set(UNIFIED_RUNTIME_TAG maxime/L0-optimizations) if(SYCL_PI_UR_OVERRIDE_FETCH_CONTENT_REPO) set(UNIFIED_RUNTIME_REPO "${SYCL_PI_UR_OVERRIDE_FETCH_CONTENT_REPO}") From 6079ab19ceb31b164e5b311614eda6be72c615d5 Mon Sep 17 00:00:00 2001 From: Maxime France-Pillois Date: Thu, 7 Mar 2024 10:24:06 +0000 Subject: [PATCH 14/14] Add define to force imm-cmd-list --- sycl/source/detail/graph_impl.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sycl/source/detail/graph_impl.cpp b/sycl/source/detail/graph_impl.cpp index 3044b7998a86d..efdb208421d60 100644 --- a/sycl/source/detail/graph_impl.cpp +++ b/sycl/source/detail/graph_impl.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#define FORCE_IMM_CMD_LIST 0 + #include #include #include @@ -681,10 +683,13 @@ sycl::detail::pi::PiExtSyncPoint exec_graph_impl::enqueueNode( void exec_graph_impl::createCommandBuffers( sycl::device Device, std::shared_ptr &Partition) { sycl::detail::pi::PiExtCommandBuffer OutCommandBuffer; + auto imm_cmd_list = (Partition->MIsInOrderGraph && !MEnableProfiling); +#if FORCE_IMM_CMD_LIST == 1 + imm_cmd_list = true; +#endif sycl::detail::pi::PiExtCommandBufferDesc Desc{ pi_ext_structure_type::PI_EXT_STRUCTURE_TYPE_COMMAND_BUFFER_DESC, nullptr, - pi_bool(Partition->MIsInOrderGraph && !MEnableProfiling), - pi_bool(MEnableProfiling)}; + pi_bool(imm_cmd_list), pi_bool(MEnableProfiling)}; auto ContextImpl = sycl::detail::getSyclObjImpl(MContext); const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin(); auto DeviceImpl = sycl::detail::getSyclObjImpl(Device);