Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions devops/compat_ci_exclude.sycl-rel-6_3
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ Matrix/joint_matrix_bf16_fill_k_cache_runtime_dim.cpp
# See GSD-11097.
Assert/assert_in_kernels.cpp

# https://github.com/intel/llvm/pull/20159 prevents returning last event as an
# optimization for submitting barrier to an empty IOQ. However, the test
# actually checks whether last event is returned or not, so it needs to be
# updated to match the new behavior. ext_oneapi_submit_barrier spec doesn't
# require last event to be returned, so this is not an ABI break.
InorderQueue/in_order_ext_oneapi_submit_barrier.cpp

Comment on lines +12 to +18
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xtian-github @gmlueck I'd need approval for excluding InorderQueue/in_order_ext_oneapi_submit_barrier.cpp from 6.3 ABI compatibility testing. This test checks whether last event is returned by ext_oneapi_submit_barrier() but after this PR, we no longer return last event. Returning last event is not required by ext_oneapi_submit_barrier spec, so it is not strictly an ABI break.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is OK, but just checking to make sure I understand ... The spec for queue::ext_oneapi_submit_barrier does require that function to return an event. However, the test was checking to see if the returned event was the last event (i.e. the event that was returned from the previous submit). This is an implementation detail, not part of the specified API. Therefore, the test being excluded is not really testing the API; it's testing the implementation. Since the implementation changed, we need to change the test also.

Is that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's correct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for confirming. I approved.

# Likely OK, but need author to provide justification, get approval/confirmation
# from someone:

Expand Down
27 changes: 4 additions & 23 deletions sycl/source/queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,24 +334,6 @@ void queue::wait_and_throw_proxy(const detail::code_location &CodeLoc) {
impl->wait_and_throw(CodeLoc);
}

static event
getBarrierEventForInorderQueueHelper(detail::queue_impl &QueueImpl) {
// This function should not be called when a queue is recording to a graph,
// as a graph can record from multiple queues and we cannot guarantee the
// last node added by an in-order queue will be the last node added to the
// graph.
assert(!QueueImpl.hasCommandGraph() &&
"Should not be called in on graph recording.");

sycl::detail::optional<event> LastEvent = QueueImpl.getLastEvent();
if (LastEvent)
return *LastEvent;

// If there was no last event, we create an empty one.
return detail::createSyclObjFromImpl<event>(
detail::event_impl::create_default_event());
}

/// Prevents any commands submitted afterward to this queue from executing
/// until all commands previously submitted to this queue have entered the
/// complete state.
Expand All @@ -374,18 +356,17 @@ event queue::ext_oneapi_submit_barrier(const detail::code_location &CodeLoc) {
/// group is being enqueued on.
event queue::ext_oneapi_submit_barrier(const std::vector<event> &WaitList,
const detail::code_location &CodeLoc) {

// If waitlist contains only empty, default constructed events, ignore
// them.
bool AllEventsEmptyOrNop = std::all_of(
begin(WaitList), end(WaitList), [&](const event &Event) -> bool {
detail::event_impl &EventImpl = *detail::getSyclObjImpl(Event);
return (EventImpl.isDefaultConstructed() || EventImpl.isNOP()) &&
!EventImpl.hasCommandGraph();
});
if (is_in_order() && !impl->hasCommandGraph() && !impl->MIsProfilingEnabled &&
AllEventsEmptyOrNop) {
return getBarrierEventForInorderQueueHelper(*impl);
}

if (WaitList.empty())
if (WaitList.empty() || AllEventsEmptyOrNop)
return submit([=](handler &CGH) { CGH.ext_oneapi_barrier(); }, CodeLoc);
else
return submit([=](handler &CGH) { CGH.ext_oneapi_barrier(WaitList); },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,28 +53,13 @@ int main() {
std::cout << "Test 2" << std::endl;
*Res = 0;

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

Q.wait();
assert(*Res == 10);
}

{
// Test cast 3 - empty queue.
std::cout << "Test 3" << std::endl;
sycl::queue EmptyQ({sycl::property::queue::in_order{}});
auto BarrierEvent = EmptyQ.ext_oneapi_submit_barrier();
assert(
BarrierEvent.get_info<sycl::info::event::command_execution_status>() ==
sycl::info::event_command_status::complete);
BarrierEvent.wait();
}
Comment on lines -67 to -76
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this test removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexeySachkov Here's my line of reasoning:
IIUC, for IOQs, ext_submit_barrier() is non-blocking and returns an event, whose state will transition to complete, when all previously submitted commands to IOQ also completes. Now, when we submit a barrier to an empty IOQ, (1) should the implementation immediately return a completed event or (2) can a non-blocking implementation return an event, take some time to figure out if queue is empty or not, and if empty, transition the event to be completed?
The test checks for (1) but IIUC, spec doesn't mandate that.
Looking at UR's implementation of urEnqueueEventsWaitWithBarrierExt, it follows (2) - it returns an event and submits zeCommandListAppendSignalEvent to L0. That's why this test was flakily failing in pre-commit CI of this PR. Before this PR, at SYCL RT level, we check if queue is empty or not and according return a completed event or submit urEnqueueEventsWaitWithBarrierExt. Since getting last event and checking whether queue is empty or not is expensive and (1) is not mandated by spec, I removed the SYCL RT check along with this test.


{
// Test cast 4 - graph.
sycl::queue GQueue{sycl::property::queue::in_order{}};
Expand Down
48 changes: 0 additions & 48 deletions sycl/test-e2e/Regression/ext_oneapi_barrier_opt.cpp

This file was deleted.

1 change: 1 addition & 0 deletions sycl/unittests/Extensions/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ add_sycl_unittest(ExtensionsTests OBJECT
OneAPIProd.cpp
EnqueueFunctionsEvents.cpp
EnqueueFunctionsPrefetch.cpp
ExtOneapiBarrierOpt.cpp
ProfilingTag.cpp
KernelProperties.cpp
NoDeviceIPVersion.cpp
Expand Down
60 changes: 60 additions & 0 deletions sycl/unittests/Extensions/ExtOneapiBarrierOpt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//==------------------- ExtOneapiBarrierOpt.cpp ----------------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <gtest/gtest.h>
#include <helpers/ScopedEnvVar.hpp>
#include <helpers/UrMock.hpp>
#include <sycl/sycl.hpp>

using namespace sycl;

inline thread_local uint32_t NumEventsInWaitList;

static ur_result_t redefinedEnqueueEventsWaitWithBarrierExt(void *pParams) {
auto params =
*static_cast<ur_enqueue_events_wait_with_barrier_ext_params_t *>(pParams);
NumEventsInWaitList = *(params.pnumEventsInWaitList);
return UR_RESULT_SUCCESS;
}

class ExtOneapiBarrierOptTest : public ::testing::Test {
public:
ExtOneapiBarrierOptTest() : Mock{} {}

protected:
void SetUp() override { NumEventsInWaitList = 0; }

protected:
sycl::unittest::UrMock<> Mock;
};

// Check that ext_oneapi_submit_barrier works fine in the scenarios
// when provided waitlist consists of only empty events.
// Tets for https://github.com/intel/llvm/pull/12951
TEST(ExtOneapiBarrierOptTest, EmptyEventTest) {
sycl::queue q1{{sycl::property::queue::in_order()}};

mock::getCallbacks().set_after_callback(
"urEnqueueEventsWaitWithBarrierExt",
&redefinedEnqueueEventsWaitWithBarrierExt);

NumEventsInWaitList = 100;
q1.ext_oneapi_submit_barrier();
ASSERT_EQ(0u, NumEventsInWaitList);

// ext_oneapi_submit_barrier should ignore empty, default constructed events.
sycl::event E1{};
NumEventsInWaitList = 100;
q1.ext_oneapi_submit_barrier({E1});
ASSERT_EQ(0u, NumEventsInWaitList);

sycl::event E2{};
NumEventsInWaitList = 100;
q1.ext_oneapi_submit_barrier({E1, E2});
ASSERT_EQ(0u, NumEventsInWaitList);
}