Skip to content

[SYCL] Deprecate SYCL 1.2.1 device selectors #6599

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
75 changes: 35 additions & 40 deletions sycl/doc/GetStartedGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ SYCL_BE=PI_CUDA ./simple-sycl-app-cuda.exe
```

**NOTE**: DPC++/SYCL developers can specify SYCL device for execution using
device selectors (e.g. `sycl::cpu_selector`, `sycl::gpu_selector`,
device selectors (e.g. `sycl::cpu_selector_v`, `sycl::gpu_selector_v`,
[Intel FPGA selector(s)](extensions/supported/sycl_ext_intel_fpga_device_selector.md)) as
explained in following section [Code the program for a specific
GPU](#code-the-program-for-a-specific-gpu).
Expand Down Expand Up @@ -740,42 +740,38 @@ the CMake.

### Code the program for a specific GPU

To specify OpenCL device SYCL provides the abstract `sycl::device_selector`
class which the can be used to define how the runtime should select the best
device.

The method `sycl::device_selector::operator()` of the SYCL
`sycl::device_selector` is an abstract member function which takes a
reference to a SYCL device and returns an integer score. This abstract member
function can be implemented in a derived class to provide a logic for selecting
a SYCL device. SYCL runtime uses the device for with the highest score is
returned. Such object can be passed to `sycl::queue` and `sycl::device`
constructors.

The example below illustrates how to use `sycl::device_selector` to create
device and queue objects bound to Intel GPU device:
To assist in finding a specific SYCL compatible device out of all that may be
available, a "device selector" may be used. A "device selector" is a ranking
function (C++ Callable) that will give an integer ranking value to all the
devices on the system. It can be passed to `sycl::queue`, `sycl::device` and
`sycl::platform` constructors. The highest ranking device is then selected. SYCL
has built-in device selectors for selecting a generic GPU, CPU, or accelerator
device, as well as one for a default device. Additionally, a user can define
their own as function, lambda, or functor class. Device selectors returning
negative values will "reject" a device ensuring it is not selected, but values 0
or higher will be selected by the highest score with ties resolved by an
internal algorithm (see Section 4.6.1 of the SYCL 2020 specification)

The example below illustrates how to use a device selector to create device and
queue objects bound to Intel GPU device:

```c++
#include <sycl/sycl.hpp>

int main() {
class NEOGPUDeviceSelector : public sycl::device_selector {
public:
int operator()(const sycl::device &Device) const override {
using namespace sycl::info;

const std::string DeviceName = Device.get_info<device::name>();
const std::string DeviceVendor = Device.get_info<device::vendor>();
auto NEOGPUDeviceSelector = [](const sycl::device &Device){
using namespace sycl::info;

return Device.is_gpu() && (DeviceName.find("HD Graphics NEO") != std::string::npos);
}
const std::string DeviceName = Device.get_info<device::name>();
bool match = Device.is_gpu() && (DeviceName.find("HD Graphics NEO") != std::string::npos);
return match ? 1 : -1;
};

NEOGPUDeviceSelector Selector;
try {
sycl::queue Queue(Selector);
sycl::device Device(Selector);
} catch (sycl::invalid_parameter_error &E) {
sycl::queue Queue(NEOGPUDeviceSelector);
sycl::device Device(NEOGPUDeviceSelector);
} catch (sycl::exception &E) {
std::cout << E.what() << std::endl;
}
}
Expand All @@ -786,19 +782,18 @@ The device selector below selects an NVIDIA device only, and won't execute if
there is none.

```c++
class CUDASelector : public sycl::device_selector {
public:
int operator()(const sycl::device &Device) const override {
using namespace sycl::info;
const std::string DriverVersion = Device.get_info<device::driver_version>();

if (Device.is_gpu() && (DriverVersion.find("CUDA") != std::string::npos)) {
std::cout << " CUDA device found " << std::endl;
return 1;
};
return -1;
}
};

int CUDASelector(const sycl::device &Device) {
using namespace sycl::info;
const std::string DriverVersion = Device.get_info<device::driver_version>();

if (Device.is_gpu() && (DriverVersion.find("CUDA") != std::string::npos)) {
std::cout << " CUDA device found " << std::endl;
return 1;
};
return -1;
}

```

### Using the DPC++ toolchain on CUDA platforms
Expand Down
5 changes: 2 additions & 3 deletions sycl/doc/MultiTileCardWithLevelZero.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@ try {
``` C++
try {
// The queue is attached to the root-device, driver distributes to sub-devices, if any.
auto D = device(gpu_selector{});
auto Q = queue(D);
auto Q = queue(gpu_selector_v);
Q.submit([&](handler& cgh) {...});
}
```
Expand All @@ -155,7 +154,7 @@ try {
- Example:
``` C++
try {
auto P = platform(gpu_selector{});
auto P = platform(gpu_selector_v);
auto RootDevices = P.get_devices();
auto C = context(RootDevices);
for (auto &D : RootDevices) {
Expand Down
2 changes: 1 addition & 1 deletion sycl/doc/design/GlobalObjectsInRuntime.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ like in example below:
sycl::queue Queue;

int main() {
Queue = sycl::queue{sycl::default_selector{}.select_device()};
Queue = sycl::queue{sycl::default_selector_v};
Copy link
Contributor

Choose a reason for hiding this comment

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

This example might not be best suited here anymore. default_selector_v is a function in our implementation so there is no "race" between it and Queue object created at line 22.

Line 25 is also useless now as the Queue is already initialized to the default device.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree about Line 25, but I think we should leave it. The whole text is about how you get undefined behavior when using global objects because the C++ standard does not specify creation/destruction order, and how the example seems syntactically correct, yet is still undefined behavior. If we remove 25 then the surrounding text isn't really making a point.

Copy link
Contributor

Choose a reason for hiding this comment

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

Where is UB here now?

Copy link
Contributor Author

@cperkinsintel cperkinsintel Sep 7, 2022

Choose a reason for hiding this comment

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

the queue is created outside main. The "seems syntactically correct" part is declaring the queue outside main but initializing it inside main. If we remove line 25 there is no "seems syntactically correct" part. The example is intended to be intentionally wrong. Read the entire section and you'll see what I mean.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

probably the whole thing should be re-written, but that's outside the scope of this PR. I'm just trying to bring the example up to date, not address its overall point.

Copy link
Contributor

Choose a reason for hiding this comment

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

part is declaring the queue outside main but initializing it inside main

I don't think it's true. We do create and define a queue outside main. Then we override the value inside the variable with another one, while the original is being destroyed.

Copy link
Contributor Author

@cperkinsintel cperkinsintel Sep 7, 2022

Choose a reason for hiding this comment

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

correct. but to make that point, we need to keep line 25. This isn't real code, this is documentation talking about global object usage.

Copy link
Contributor

Choose a reason for hiding this comment

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

Still, where is UB?

Copy link
Contributor Author

@cperkinsintel cperkinsintel Sep 7, 2022

Choose a reason for hiding this comment

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


return 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ int main(void) {
int err_cnt = 0;

try {
queue q(gpu_selector{}, createExceptionHandler());
queue q(gpu_selector_v, createExceptionHandler());
auto dev = q.get_device();
std::cout << "Running on " << dev.get_info<info::device::name>() << "\n";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ As encouraged by the SYCL specification, a feature-test macro, `SYCL_EXT_ONEAPI_
## Examples

```c++
sycl::device gpu = sycl::device{sycl::gpu_selector{}};
sycl::device gpu = sycl::device{sycl::gpu_selector_v};
std::cout << gpu.get_info<sycl::info::device::name>() << '\n';

#ifdef SYCL_EXT_ONEAPI_MAX_WORK_GROUP_QUERY
Expand Down
2 changes: 2 additions & 0 deletions sycl/include/sycl/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class __SYCL_EXPORT device {
/// by the DeviceSelector provided.
///
/// \param DeviceSelector SYCL 1.2.1 device_selector to be used (see 4.6.1.1).
__SYCL2020_DEPRECATED("Use Callable device selectors instead of deprecated "
"device_selector subclasses.")
explicit device(const device_selector &DeviceSelector);

#if __cplusplus >= 201703L
Expand Down
23 changes: 17 additions & 6 deletions sycl/include/sycl/device_selector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class filter_selector;
/// \sa device
///
/// \ingroup sycl_api_dev_sel
class __SYCL_EXPORT device_selector {
class __SYCL_EXPORT __SYCL2020_DEPRECATED(
"Use Callable instead to select device.") device_selector {

public:
virtual ~device_selector() = default;
Expand All @@ -46,7 +47,9 @@ class __SYCL_EXPORT device_selector {
/// \sa device
///
/// \ingroup sycl_api_dev_sel
class __SYCL_EXPORT default_selector : public device_selector {
class __SYCL_EXPORT __SYCL2020_DEPRECATED(
"Use the callable sycl::default_selector_v instead.") default_selector
: public device_selector {
public:
int operator()(const device &dev) const override;
};
Expand All @@ -56,7 +59,9 @@ class __SYCL_EXPORT default_selector : public device_selector {
/// \sa device
///
/// \ingroup sycl_api_dev_sel
class __SYCL_EXPORT gpu_selector : public device_selector {
class __SYCL_EXPORT __SYCL2020_DEPRECATED(
"Use the callable sycl::gpu_selector_v instead.") gpu_selector
: public device_selector {
public:
int operator()(const device &dev) const override;
};
Expand All @@ -66,7 +71,9 @@ class __SYCL_EXPORT gpu_selector : public device_selector {
/// \sa device
///
/// \ingroup sycl_api_dev_sel
class __SYCL_EXPORT cpu_selector : public device_selector {
class __SYCL_EXPORT __SYCL2020_DEPRECATED(
"Use the callable sycl::cpu_selector_v instead.") cpu_selector
: public device_selector {
public:
int operator()(const device &dev) const override;
};
Expand All @@ -76,7 +83,9 @@ class __SYCL_EXPORT cpu_selector : public device_selector {
/// \sa device
///
/// \ingroup sycl_api_dev_sel
class __SYCL_EXPORT accelerator_selector : public device_selector {
class __SYCL_EXPORT
__SYCL2020_DEPRECATED("Use the callable sycl::accelerator_selector_v instead.")
accelerator_selector : public device_selector {
public:
int operator()(const device &dev) const override;
};
Expand All @@ -86,7 +95,9 @@ class __SYCL_EXPORT accelerator_selector : public device_selector {
/// \sa device
///
/// \ingroup sycl_api_dev_sel
class __SYCL_EXPORT host_selector : public device_selector {
class __SYCL_EXPORT
__SYCL2020_DEPRECATED("Use a callable function instead.") host_selector
: public device_selector {
public:
int operator()(const device &dev) const override;
};
Expand Down
2 changes: 2 additions & 0 deletions sycl/include/sycl/platform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class __SYCL_EXPORT platform {
/// provided device selector.
///
/// \param DeviceSelector is an instance of a SYCL 1.2.1 device_selector
__SYCL2020_DEPRECATED("Use Callable device selectors instead of deprecated "
"device_selector subclasses.")
explicit platform(const device_selector &DeviceSelector);

#if __cplusplus >= 201703L
Expand Down
8 changes: 8 additions & 0 deletions sycl/include/sycl/queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ class __SYCL_EXPORT queue {
///
/// \param DeviceSelector is an instance of a SYCL 1.2.1 device_selector.
/// \param PropList is a list of properties for queue construction.
__SYCL2020_DEPRECATED("Use Callable device selectors instead of deprecated "
"device_selector subclasses.")
queue(const device_selector &DeviceSelector,
const property_list &PropList = {})
: queue(DeviceSelector.select_device(), async_handler{}, PropList) {}
Expand All @@ -173,6 +175,8 @@ class __SYCL_EXPORT queue {
/// \param DeviceSelector is an instance of SYCL 1.2.1 device_selector.
/// \param AsyncHandler is a SYCL asynchronous exception handler.
/// \param PropList is a list of properties for queue construction.
__SYCL2020_DEPRECATED("Use Callable device selectors instead of deprecated "
"device_selector subclasses.")
queue(const device_selector &DeviceSelector,
const async_handler &AsyncHandler, const property_list &PropList = {})
: queue(DeviceSelector.select_device(), AsyncHandler, PropList) {}
Expand All @@ -199,6 +203,8 @@ class __SYCL_EXPORT queue {
/// \param SyclContext is an instance of SYCL context.
/// \param DeviceSelector is an instance of SYCL device selector.
/// \param PropList is a list of properties for queue construction.
__SYCL2020_DEPRECATED("Use Callable device selectors instead of deprecated "
"device_selector subclasses.")
queue(const context &SyclContext, const device_selector &DeviceSelector,
const property_list &PropList = {});

Expand All @@ -210,6 +216,8 @@ class __SYCL_EXPORT queue {
/// \param DeviceSelector is an instance of SYCL device selector.
/// \param AsyncHandler is a SYCL asynchronous exception handler.
/// \param PropList is a list of properties for queue construction.
__SYCL2020_DEPRECATED("Use Callable device selectors instead of deprecated "
"device_selector subclasses.")
queue(const context &SyclContext, const device_selector &DeviceSelector,
const async_handler &AsyncHandler, const property_list &PropList = {});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void store(atomic_t foo, int value) { foo.store(value); }

int main(int argc, char *argv[]) {

queue q(default_selector{});
queue q(default_selector_v);

// Accessor with dimensionality 0.
{
Expand Down
2 changes: 1 addition & 1 deletion sycl/test/extensions/inline_asm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ int main() {
sycl::buffer<DataType, 1> BufB(DataB, DEFAULT_PROBLEM_SIZE);
sycl::buffer<DataType, 1> BufC(DataC, DEFAULT_PROBLEM_SIZE);

sycl::queue deviceQueue(sycl::gpu_selector{}, AsyncHandler);
sycl::queue deviceQueue(sycl::gpu_selector_v, AsyncHandler);

deviceQueue.submit([&](sycl::handler &cgh) {
auto A = BufA.get_access<sycl::access::mode::read>(cgh);
Expand Down
13 changes: 12 additions & 1 deletion sycl/test/warnings/sycl_2020_deprecations.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clangxx %fsycl-host-only -fsyntax-only -sycl-std=2020 -Xclang -verify -Xclang -verify-ignore-unexpected=note %s -o %t.out
// RUN: %clangxx %fsycl-host-only -fsyntax-only -ferror-limit=100 -sycl-std=2020 -Xclang -verify -Xclang -verify-ignore-unexpected=note %s -o %t.out

#include <CL/sycl.hpp>
#include <sycl/ext/intel/online_compiler.hpp>
Expand Down Expand Up @@ -194,6 +194,17 @@ int main() {
// expected-warning@+1{{'get_linear_id' is deprecated: use sycl::group::get_group_linear_id() instead}}
group.get_linear_id();

// expected-warning@+1{{'default_selector' is deprecated: Use the callable sycl::default_selector_v instead.}}
sycl::default_selector ds;
// expected-warning@+1{{'cpu_selector' is deprecated: Use the callable sycl::cpu_selector_v instead.}}
sycl::cpu_selector cs;
// expected-warning@+1{{'gpu_selector' is deprecated: Use the callable sycl::gpu_selector_v instead.}}
sycl::gpu_selector gs;
// expected-warning@+1{{'accelerator_selector' is deprecated: Use the callable sycl::accelerator_selector_v instead.}}
sycl::accelerator_selector as;
// expected-warning@+1{{'host_selector' is deprecated: Use a callable function instead.}}
sycl::host_selector hs;

// expected-warning@+2{{'local' is deprecated: use `local_accessor` instead}}
Queue.submit([&](sycl::handler &CGH) {
sycl::accessor<int, 1, sycl::access::mode::read_write, sycl::target::local>
Expand Down
8 changes: 4 additions & 4 deletions sycl/unittests/assert/assert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ void ChildProcess(int StdErrFD) {
exit(1);
}

sycl::platform Plt{sycl::default_selector()};
sycl::platform Plt;

sycl::unittest::PiMock Mock{Plt};

Expand Down Expand Up @@ -516,7 +516,7 @@ void ParentProcess(int ChildPID, int ChildStdErrFD) {
TEST(Assert, TestPositive) {
// Preliminary checks
{
sycl::platform Plt{sycl::default_selector()};
sycl::platform Plt;
if (Plt.is_host()) {
printf("Test is not supported on host, skipping\n");
return;
Expand Down Expand Up @@ -572,7 +572,7 @@ TEST(Assert, TestAssertServiceKernelHidden) {
}

TEST(Assert, TestInteropKernelNegative) {
sycl::platform Plt{sycl::default_selector()};
sycl::platform Plt;

if (Plt.is_host()) {
printf("Test is not supported on host, skipping\n");
Expand Down Expand Up @@ -610,7 +610,7 @@ TEST(Assert, TestInteropKernelNegative) {
}

TEST(Assert, TestInteropKernelFromProgramNegative) {
sycl::platform Plt{sycl::default_selector()};
sycl::platform Plt;

if (Plt.is_host()) {
printf("Test is not supported on host, skipping\n");
Expand Down
2 changes: 1 addition & 1 deletion sycl/unittests/buffer/BufferLocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static pi_result redefinedDeviceGetInfo(pi_device device,

class BufferTest : public ::testing::Test {
public:
BufferTest() : Plt{sycl::default_selector()} {}
BufferTest() {}

protected:
void SetUp() override {
Expand Down