Skip to content

Commit 0f04fcb

Browse files
1 parent aecfc0e commit 0f04fcb

File tree

7 files changed

+216
-5
lines changed

7 files changed

+216
-5
lines changed

sycl/doc/extensions/proposed/sycl_ext_oneapi_current_device.asciidoc renamed to sycl/doc/extensions/experimental/sycl_ext_oneapi_current_device.asciidoc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ SYCL specification refer to that revision.
4343

4444
== Status
4545

46-
This is a proposed extension specification, intended to gather community
47-
feedback. Interfaces defined in this specification may not be implemented yet
48-
or may be in a preliminary state. The specification itself may also change in
49-
incompatible ways before it is finalized. *Shipping software products should
50-
not rely on APIs defined in this specification.*
46+
This is an experimental extension specification, intended to provide early
47+
access to features and gather community feedback. Interfaces defined in this
48+
specification are implemented in {dpcpp}, but they are not finalized and may
49+
change incompatibly in future versions of {dpcpp} without prior notice.
50+
*Shipping software products should not rely on APIs defined in this
51+
specification.*
5152

5253
== Overview
5354

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//==--------- current_device.hpp - sycl_ext_oneapi_current_device ----------==//
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+
#pragma once
10+
11+
#include <sycl/device.hpp>
12+
13+
namespace sycl {
14+
inline namespace _V1 {
15+
namespace ext::oneapi::experimental::this_thread {
16+
17+
namespace detail {
18+
inline sycl::device &get_current_device_ref() {
19+
static thread_local sycl::device current_device{sycl::default_selector_v};
20+
return current_device;
21+
}
22+
} // namespace detail
23+
24+
/// @return The current default device for the calling host thread. If
25+
/// `set_current_device()` has not been called by this thread, returns the
26+
/// device selected by the default device selector.
27+
///
28+
/// @pre The function is called from a host thread, executing outside of a host
29+
/// task or an asynchronous error handler.
30+
inline sycl::device get_current_device() {
31+
return detail::get_current_device_ref();
32+
}
33+
34+
/// @brief Sets the current default device to `dev` for the calling host thread.
35+
///
36+
/// @pre The function is called from a host thread, executing outside of a host
37+
/// task or an asynchronous error handler.
38+
inline void set_current_device(sycl::device dev) {
39+
detail::get_current_device_ref() = dev;
40+
}
41+
42+
} // namespace ext::oneapi::experimental::this_thread
43+
} // namespace _V1
44+
} // namespace sycl

sycl/include/sycl/sycl.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
#include <sycl/ext/oneapi/experimental/cluster_group_prop.hpp>
9494
#include <sycl/ext/oneapi/experimental/composite_device.hpp>
9595
#include <sycl/ext/oneapi/experimental/cuda/barrier.hpp>
96+
#include <sycl/ext/oneapi/experimental/current_device.hpp>
9697
#include <sycl/ext/oneapi/experimental/enqueue_functions.hpp>
9798
#include <sycl/ext/oneapi/experimental/fixed_size_group.hpp>
9899
#include <sycl/ext/oneapi/experimental/forward_progress.hpp>

sycl/source/feature_test.hpp.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ inline namespace _V1 {
114114
#define SYCL_EXT_ONEAPI_WORK_GROUP_STATIC 1
115115
#define SYCL_EXT_ONEAPI_NUM_COMPUTE_UNITS 1
116116
#define SYCL_EXT_ONEAPI_DEVICE_IMAGE_BACKEND_CONTENT 1
117+
#define SYCL_EXT_ONEAPI_CURRENT_DEVICE 1
117118
#define SYCL_KHR_FREE_FUNCTION_COMMANDS 1
118119
// In progress yet
119120
#define SYCL_EXT_ONEAPI_ATOMIC16 0
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// REQUIRES: any-device-is-cpu, any-device-is-gpu
2+
3+
// RUN: %{build} -o %t.out %threads_lib
4+
// RUN: %{run-unfiltered-devices} %t.out
5+
6+
// E2E tests for sycl_ext_oneapi_current_device
7+
8+
#include <sycl/ext/oneapi/experimental/current_device.hpp>
9+
10+
#include <thread>
11+
12+
void check_get_eq(sycl::device dev) {
13+
auto device =
14+
sycl::ext::oneapi::experimental::this_thread::get_current_device();
15+
if (device != dev)
16+
assert(false && "check_get_eq failed.");
17+
}
18+
19+
void check_get_ne(sycl::device dev) {
20+
auto device =
21+
sycl::ext::oneapi::experimental::this_thread::get_current_device();
22+
if (device == dev)
23+
assert(false && "check_get_ne failed.");
24+
}
25+
26+
void check_set_get_eq(sycl::device dev) {
27+
sycl::ext::oneapi::experimental::this_thread::set_current_device(dev);
28+
auto device =
29+
sycl::ext::oneapi::experimental::this_thread::get_current_device();
30+
if (device != dev)
31+
assert(false && "check_set_get_eq failed.");
32+
}
33+
34+
int main() {
35+
// Test 1
36+
std::thread t1(check_get_eq, sycl::device{sycl::default_selector_v});
37+
std::thread t2(check_get_eq, sycl::device{sycl::default_selector_v});
38+
39+
t1.join();
40+
t2.join();
41+
42+
// Test 2
43+
// As GPU device is required, it is always has higher score than CPU device,
44+
// so test must not fail.
45+
t1 = std::thread(check_get_ne, sycl::device{sycl::cpu_selector_v});
46+
t2 = std::thread(check_get_ne, sycl::device{sycl::cpu_selector_v});
47+
48+
t1.join();
49+
t2.join();
50+
51+
// Test 3
52+
t1 = std::thread(check_set_get_eq, sycl::device{sycl::cpu_selector_v});
53+
t2 = std::thread(check_set_get_eq, sycl::device{sycl::gpu_selector_v});
54+
55+
t1.join();
56+
t2.join();
57+
58+
// Test 4
59+
auto device_1 =
60+
sycl::ext::oneapi::experimental::this_thread::get_current_device();
61+
if (device_1 != sycl::device{sycl::default_selector_v})
62+
assert(false && "get_current_device check failed.");
63+
64+
// Test 5
65+
sycl::ext::oneapi::experimental::this_thread::set_current_device(
66+
sycl::device{sycl::cpu_selector_v});
67+
auto device_2 =
68+
sycl::ext::oneapi::experimental::this_thread::get_current_device();
69+
if (device_2 != sycl::device{sycl::cpu_selector_v})
70+
assert(false && "set/get_current_device check failed.");
71+
72+
return 0;
73+
}

sycl/unittests/Extensions/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
set(CMAKE_CXX_EXTENSIONS OFF)
22

33
add_sycl_unittest(ExtensionsTests OBJECT
4+
CurrentDevice.cpp
45
DefaultContext.cpp
56
FPGADeviceSelectors.cpp
67
DeviceArchitecture.cpp
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//==---- CurrentDevice.cpp -- sycl_ext_oneapi_current_device unit tests ----==//
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 <sycl/sycl.hpp>
10+
11+
#include <helpers/UrMock.hpp>
12+
13+
#include <gtest/gtest.h>
14+
#include <thread>
15+
16+
namespace {
17+
const auto DEVICE_CPU = reinterpret_cast<ur_device_handle_t>(1u);
18+
const auto DEVICE_GPU = reinterpret_cast<ur_device_handle_t>(2u);
19+
20+
ur_result_t redefine_urDeviceGet(void *pParams) {
21+
auto params = *static_cast<ur_device_get_params_t *>(pParams);
22+
if (*params.ppNumDevices)
23+
**params.ppNumDevices = 2;
24+
if (*params.pphDevices && *params.pNumEntries > 0) {
25+
(*params.pphDevices)[0] = DEVICE_CPU;
26+
(*params.pphDevices)[1] = DEVICE_GPU;
27+
}
28+
return UR_RESULT_SUCCESS;
29+
}
30+
31+
ur_result_t after_urDeviceGetInfo(void *pParams) {
32+
auto params = *static_cast<ur_device_get_info_params_t *>(pParams);
33+
switch (*params.ppropName) {
34+
case UR_DEVICE_INFO_TYPE: {
35+
ur_device_type_t UrDeviceType = UR_DEVICE_TYPE_DEFAULT;
36+
if (*params.phDevice == DEVICE_CPU) {
37+
UrDeviceType = UR_DEVICE_TYPE_CPU;
38+
} else if (*params.phDevice == DEVICE_GPU) {
39+
UrDeviceType = UR_DEVICE_TYPE_GPU;
40+
}
41+
if (*params.ppPropValue)
42+
*static_cast<ur_device_type_t *>(*params.ppPropValue) = UrDeviceType;
43+
if (*params.ppPropSizeRet)
44+
**params.ppPropSizeRet = sizeof(UrDeviceType);
45+
return UR_RESULT_SUCCESS;
46+
}
47+
default:
48+
return UR_RESULT_SUCCESS;
49+
}
50+
}
51+
52+
void callable_set_get_eq(sycl::device dev) {
53+
sycl::ext::oneapi::experimental::this_thread::set_current_device(dev);
54+
ASSERT_NO_FATAL_FAILURE(
55+
sycl::ext::oneapi::experimental::this_thread::get_current_device() = dev);
56+
}
57+
} // namespace
58+
59+
TEST(CurrentDeviceTest, CheckGetCurrentDeviceReturnDefaultDeviceInHostThread) {
60+
sycl::unittest::UrMock<> Mock;
61+
mock::getCallbacks().set_replace_callback("urDeviceGet",
62+
&redefine_urDeviceGet);
63+
ASSERT_EQ(sycl::ext::oneapi::experimental::this_thread::get_current_device(),
64+
sycl::device{sycl::default_selector_v});
65+
}
66+
67+
TEST(CurrentDeviceTest,
68+
CheckGetCurrentDeviceReturnDefaultSelectorByDefaultInTwoThreads) {
69+
sycl::unittest::UrMock<> Mock;
70+
mock::getCallbacks().set_replace_callback("urDeviceGet",
71+
&redefine_urDeviceGet);
72+
mock::getCallbacks().set_after_callback("urDeviceGetInfo",
73+
&after_urDeviceGetInfo);
74+
75+
sycl::platform Plt = sycl::platform();
76+
77+
ASSERT_EQ(Plt.get_devices().size(), 2ull);
78+
79+
sycl::device cpu_device = Plt.get_devices()[0];
80+
sycl::device gpu_device = Plt.get_devices()[1];
81+
82+
ASSERT_TRUE(cpu_device.is_cpu());
83+
ASSERT_TRUE(gpu_device.is_gpu());
84+
85+
std::thread t1(callable_set_get_eq, cpu_device);
86+
std::thread t2(callable_set_get_eq, gpu_device);
87+
88+
t1.join();
89+
t2.join();
90+
}

0 commit comments

Comments
 (0)