Skip to content

Commit 0e67db8

Browse files
authored
[SYCL] Don't select devices with no available images (#6203)
This patch solves: * [SYCL] Default selector should filter devices based on available device images #2004 * [SYCL][CUDA] Default selector behaviour #1665 In some cases the current selector may select a device for which we don't have an AOT or SPIR-V binary for, this patch ensures that such devices get skipped.
1 parent 6e89821 commit 0e67db8

File tree

3 files changed

+48
-43
lines changed

3 files changed

+48
-43
lines changed

sycl/source/detail/program_manager/program_manager.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,16 @@ kernel_id ProgramManager::getSYCLKernelID(const std::string &KernelName) {
14601460
return KernelID->second;
14611461
}
14621462

1463+
bool ProgramManager::hasCompatibleImage(const device &Dev) {
1464+
std::lock_guard<std::mutex> Guard(m_KernelIDsMutex);
1465+
1466+
return std::any_of(
1467+
m_BinImg2KernelIDs.cbegin(), m_BinImg2KernelIDs.cend(),
1468+
[&](std::pair<RTDeviceBinaryImage *,
1469+
std::shared_ptr<std::vector<kernel_id>>>
1470+
Elem) { return compatibleWithDevice(Elem.first, Dev); });
1471+
}
1472+
14631473
std::vector<kernel_id> ProgramManager::getAllSYCLKernelIDs() {
14641474
std::lock_guard<std::mutex> KernelIDsGuard(m_KernelIDsMutex);
14651475

sycl/source/detail/program_manager/program_manager.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ class ProgramManager {
188188
void addOrInitDeviceGlobalEntry(const void *DeviceGlobalPtr,
189189
const char *UniqueId);
190190

191+
// Returns true if any available image is compatible with the device Dev.
192+
bool hasCompatibleImage(const device &Dev);
193+
191194
// The function returns a vector of SYCL device images that are compiled with
192195
// the required state and at least one device from the passed list of devices.
193196
std::vector<device_image_plain> getSYCLDeviceImagesWithCompatibleState(

sycl/source/device_selector.cpp

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,27 @@
2727
__SYCL_INLINE_NAMESPACE(cl) {
2828
namespace sycl {
2929

30-
// Utility function to check if device is of the preferred backend.
31-
// Currently preference is given to the level_zero backend.
32-
static bool isDeviceOfPreferredSyclBe(const device &Device) {
30+
// SYCL_DEVICE_FILTER doesn't need to be considered in the device preferences
31+
// as it filters the device list returned by device::get_devices itself, so
32+
// only matching devices will be scored.
33+
static int getDevicePreference(const device &Device) {
34+
int Score = 0;
35+
36+
// No preferences for host devices.
3337
if (Device.is_host())
34-
return false;
38+
return Score;
39+
40+
// Strongly prefer devices with available images.
41+
auto &program_manager = cl::sycl::detail::ProgramManager::getInstance();
42+
if (program_manager.hasCompatibleImage(Device))
43+
Score += 1000;
44+
45+
// Prefer level_zero backend devices.
46+
if (detail::getSyclObjImpl(Device)->getPlugin().getBackend() ==
47+
backend::ext_oneapi_level_zero)
48+
Score += 50;
3549

36-
return detail::getSyclObjImpl(Device)->getPlugin().getBackend() ==
37-
backend::ext_oneapi_level_zero;
50+
return Score;
3851
}
3952

4053
device device_selector::select_device() const {
@@ -64,11 +77,12 @@ device device_selector::select_device() const {
6477

6578
// SYCL spec says: "If more than one device receives the high score then
6679
// one of those tied devices will be returned, but which of the devices
67-
// from the tied set is to be returned is not defined". Here we give a
68-
// preference to the device of the preferred BE.
69-
//
80+
// from the tied set is to be returned is not defined". So use the device
81+
// preference score to resolve ties, this is necessary for custom_selectors
82+
// that may not already include device preference in their scoring.
7083
if ((score < dev_score) ||
71-
(score == dev_score && isDeviceOfPreferredSyclBe(dev))) {
84+
((score == dev_score) &&
85+
(getDevicePreference(*res) < getDevicePreference(dev)))) {
7286
res = &dev;
7387
score = dev_score;
7488
}
@@ -97,25 +111,13 @@ device device_selector::select_device() const {
97111
/// 1. GPU
98112
/// 2. CPU
99113
/// 3. Host
114+
/// 4. Accelerator
100115
int default_selector::operator()(const device &dev) const {
101-
102-
int Score = REJECT_DEVICE_SCORE;
103-
104-
// Give preference to device of SYCL BE.
105-
if (isDeviceOfPreferredSyclBe(dev))
106-
Score = 50;
107-
108-
// If SYCL_DEVICE_FILTER is set, filter device gets a high point.
109-
// All unmatched devices should never be selected.
110-
detail::device_filter_list *FilterList =
111-
detail::SYCLConfig<detail::SYCL_DEVICE_FILTER>::get();
112-
// device::get_devices returns filtered list of devices.
113-
// Keep 1000 for default score when filters were applied.
114-
if (FilterList)
115-
Score = 1000;
116+
// The default selector doesn't reject any devices.
117+
int Score = 0;
116118

117119
if (dev.get_info<info::device::device_type>() == detail::get_forced_type())
118-
Score += 1000;
120+
Score += 2000;
119121

120122
if (dev.is_gpu())
121123
Score += 500;
@@ -132,18 +134,18 @@ int default_selector::operator()(const device &dev) const {
132134
if (dev.is_accelerator())
133135
Score += 75;
134136

137+
// Add preference score.
138+
Score += getDevicePreference(dev);
139+
135140
return Score;
136141
}
137142

138143
int gpu_selector::operator()(const device &dev) const {
139144
int Score = REJECT_DEVICE_SCORE;
140145

141146
if (dev.is_gpu()) {
142-
// device::get_devices returns filtered list of devices.
143147
Score = 1000;
144-
// Give preference to device of SYCL BE.
145-
if (isDeviceOfPreferredSyclBe(dev))
146-
Score += 50;
148+
Score += getDevicePreference(dev);
147149
}
148150
return Score;
149151
}
@@ -152,12 +154,8 @@ int cpu_selector::operator()(const device &dev) const {
152154
int Score = REJECT_DEVICE_SCORE;
153155

154156
if (dev.is_cpu()) {
155-
// device::get_devices returns filtered list of devices.
156157
Score = 1000;
157-
158-
// Give preference to device of SYCL BE.
159-
if (isDeviceOfPreferredSyclBe(dev))
160-
Score += 50;
158+
Score += getDevicePreference(dev);
161159
}
162160
return Score;
163161
}
@@ -166,12 +164,8 @@ int accelerator_selector::operator()(const device &dev) const {
166164
int Score = REJECT_DEVICE_SCORE;
167165

168166
if (dev.is_accelerator()) {
169-
// device::get_devices returns filtered list of devices.
170167
Score = 1000;
171-
172-
// Give preference to device of SYCL BE.
173-
if (isDeviceOfPreferredSyclBe(dev))
174-
Score += 50;
168+
Score += getDevicePreference(dev);
175169
}
176170
return Score;
177171
}
@@ -181,9 +175,7 @@ int host_selector::operator()(const device &dev) const {
181175

182176
if (dev.is_host()) {
183177
Score = 1000;
184-
// Give preference to device of SYCL BE.
185-
if (isDeviceOfPreferredSyclBe(dev))
186-
Score += 50;
178+
Score += getDevicePreference(dev);
187179
}
188180
return Score;
189181
}

0 commit comments

Comments
 (0)