Skip to content

Commit 3a6b088

Browse files
[SYCL] Don't return last event in ext_oneapi_submit_barrier (#20235)
This is a cherry-pick of #20159 (and #20241) **Problem** As an optimization in `ext_oneapi_submit_barrier`, for in-order queue, when waitlist is empty, we return the last event, if it is available. However, after #18277, we no longer store last event and instead submit a marker to get the last event. And this caused performance regression in some of our internal benchmarks. **Solution** Don't return last event and instead submit a barrier with empty waitlist. Patch-by: Udit Kumar Agarwal <[email protected]>
1 parent f402a66 commit 3a6b088

File tree

5 files changed

+68
-89
lines changed

5 files changed

+68
-89
lines changed

sycl/source/queue.cpp

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -327,24 +327,6 @@ void queue::wait_and_throw_proxy(const detail::code_location &CodeLoc) {
327327
impl->wait_and_throw(CodeLoc);
328328
}
329329

330-
static event
331-
getBarrierEventForInorderQueueHelper(detail::queue_impl &QueueImpl) {
332-
// This function should not be called when a queue is recording to a graph,
333-
// as a graph can record from multiple queues and we cannot guarantee the
334-
// last node added by an in-order queue will be the last node added to the
335-
// graph.
336-
assert(!QueueImpl.hasCommandGraph() &&
337-
"Should not be called in on graph recording.");
338-
339-
sycl::detail::optional<event> LastEvent = QueueImpl.getLastEvent();
340-
if (LastEvent)
341-
return *LastEvent;
342-
343-
// If there was no last event, we create an empty one.
344-
return detail::createSyclObjFromImpl<event>(
345-
detail::event_impl::create_default_event());
346-
}
347-
348330
/// Prevents any commands submitted afterward to this queue from executing
349331
/// until all commands previously submitted to this queue have entered the
350332
/// complete state.
@@ -367,18 +349,17 @@ event queue::ext_oneapi_submit_barrier(const detail::code_location &CodeLoc) {
367349
/// group is being enqueued on.
368350
event queue::ext_oneapi_submit_barrier(const std::vector<event> &WaitList,
369351
const detail::code_location &CodeLoc) {
352+
353+
// If waitlist contains only empty, default constructed events, ignore
354+
// them.
370355
bool AllEventsEmptyOrNop = std::all_of(
371356
begin(WaitList), end(WaitList), [&](const event &Event) -> bool {
372357
detail::event_impl &EventImpl = *detail::getSyclObjImpl(Event);
373358
return (EventImpl.isDefaultConstructed() || EventImpl.isNOP()) &&
374359
!EventImpl.hasCommandGraph();
375360
});
376-
if (is_in_order() && !impl->hasCommandGraph() && !impl->MIsProfilingEnabled &&
377-
AllEventsEmptyOrNop) {
378-
return getBarrierEventForInorderQueueHelper(*impl);
379-
}
380361

381-
if (WaitList.empty())
362+
if (WaitList.empty() || AllEventsEmptyOrNop)
382363
return submit([=](handler &CGH) { CGH.ext_oneapi_barrier(); }, CodeLoc);
383364
else
384365
return submit([=](handler &CGH) { CGH.ext_oneapi_barrier(WaitList); },

sycl/test-e2e/InorderQueue/in_order_ext_oneapi_submit_barrier.cpp

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,28 +53,13 @@ int main() {
5353
std::cout << "Test 2" << std::endl;
5454
*Res = 0;
5555

56-
auto Event1 = Q.submit(
57-
[&](sycl::handler &CGH) { CGH.host_task([&] { *Res += 1; }); });
58-
auto BarrierEvent1 = Q.ext_oneapi_submit_barrier();
59-
assert(checkBarrierEvent(Q.get_backend(), Event1, BarrierEvent1,
60-
false /* host tasks used */));
61-
auto Event2 = Q.submit([&](sycl::handler &CGH) { CGH.fill(Res, 10, 1); });
56+
Q.submit([&](sycl::handler &CGH) { CGH.host_task([&] { *Res += 1; }); });
57+
Q.ext_oneapi_submit_barrier();
58+
Q.submit([&](sycl::handler &CGH) { CGH.fill(Res, 10, 1); });
6259

6360
Q.wait();
6461
assert(*Res == 10);
6562
}
66-
67-
{
68-
// Test cast 3 - empty queue.
69-
std::cout << "Test 3" << std::endl;
70-
sycl::queue EmptyQ({sycl::property::queue::in_order{}});
71-
auto BarrierEvent = EmptyQ.ext_oneapi_submit_barrier();
72-
assert(
73-
BarrierEvent.get_info<sycl::info::event::command_execution_status>() ==
74-
sycl::info::event_command_status::complete);
75-
BarrierEvent.wait();
76-
}
77-
7863
{
7964
// Test cast 4 - graph.
8065
sycl::queue GQueue{sycl::property::queue::in_order{}};

sycl/test-e2e/Regression/ext_oneapi_barrier_opt.cpp

Lines changed: 0 additions & 48 deletions
This file was deleted.

sycl/unittests/Extensions/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ add_sycl_unittest(ExtensionsTests OBJECT
1212
CompositeDevice.cpp
1313
OneAPIProd.cpp
1414
EnqueueFunctionsEvents.cpp
15+
ExtOneapiBarrierOpt.cpp
1516
ProfilingTag.cpp
1617
KernelProperties.cpp
1718
NoDeviceIPVersion.cpp
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//==------------------- ExtOneapiBarrierOpt.cpp ----------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <gtest/gtest.h>
10+
#include <helpers/ScopedEnvVar.hpp>
11+
#include <helpers/UrMock.hpp>
12+
#include <sycl/sycl.hpp>
13+
14+
using namespace sycl;
15+
16+
inline thread_local uint32_t NumEventsInWaitList;
17+
18+
static ur_result_t redefinedEnqueueEventsWaitWithBarrierExt(void *pParams) {
19+
auto params =
20+
*static_cast<ur_enqueue_events_wait_with_barrier_ext_params_t *>(pParams);
21+
NumEventsInWaitList = *(params.pnumEventsInWaitList);
22+
return UR_RESULT_SUCCESS;
23+
}
24+
25+
class ExtOneapiBarrierOptTest : public ::testing::Test {
26+
public:
27+
ExtOneapiBarrierOptTest() : Mock{} {}
28+
29+
protected:
30+
void SetUp() override { NumEventsInWaitList = 0; }
31+
32+
protected:
33+
sycl::unittest::UrMock<> Mock;
34+
};
35+
36+
// Check that ext_oneapi_submit_barrier works fine in the scenarios
37+
// when provided waitlist consists of only empty events.
38+
// Tets for https://github.com/intel/llvm/pull/12951
39+
TEST_F(ExtOneapiBarrierOptTest, EmptyEventTest) {
40+
sycl::queue q1{{sycl::property::queue::in_order()}};
41+
42+
mock::getCallbacks().set_after_callback(
43+
"urEnqueueEventsWaitWithBarrierExt",
44+
&redefinedEnqueueEventsWaitWithBarrierExt);
45+
46+
NumEventsInWaitList = 100;
47+
q1.ext_oneapi_submit_barrier();
48+
ASSERT_EQ(0u, NumEventsInWaitList);
49+
50+
// ext_oneapi_submit_barrier should ignore empty, default constructed events.
51+
sycl::event E1{};
52+
NumEventsInWaitList = 100;
53+
q1.ext_oneapi_submit_barrier({E1});
54+
ASSERT_EQ(0u, NumEventsInWaitList);
55+
56+
sycl::event E2{};
57+
NumEventsInWaitList = 100;
58+
q1.ext_oneapi_submit_barrier({E1, E2});
59+
ASSERT_EQ(0u, NumEventsInWaitList);
60+
}

0 commit comments

Comments
 (0)