-
Notifications
You must be signed in to change notification settings - Fork 797
[SYCL] Don't select devices with no available images #6203
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
Changes from all commits
326f40a
86483b9
01d278e
17305b1
f19c374
e9257cf
5d91dec
a36d209
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,14 +27,27 @@ | |
__SYCL_INLINE_NAMESPACE(cl) { | ||
namespace sycl { | ||
|
||
// Utility function to check if device is of the preferred backend. | ||
// Currently preference is given to the level_zero backend. | ||
static bool isDeviceOfPreferredSyclBe(const device &Device) { | ||
// SYCL_DEVICE_FILTER doesn't need to be considered in the device preferences | ||
// as it filters the device list returned by device::get_devices itself, so | ||
// only matching devices will be scored. | ||
static int getDevicePreference(const device &Device) { | ||
int Score = 0; | ||
|
||
// No preferences for host devices. | ||
if (Device.is_host()) | ||
return false; | ||
return Score; | ||
|
||
// Strongly prefer devices with available images. | ||
auto &program_manager = cl::sycl::detail::ProgramManager::getInstance(); | ||
if (program_manager.hasCompatibleImage(Device)) | ||
Score += 1000; | ||
|
||
// Prefer level_zero backend devices. | ||
if (detail::getSyclObjImpl(Device)->getPlugin().getBackend() == | ||
backend::ext_oneapi_level_zero) | ||
Score += 50; | ||
|
||
return detail::getSyclObjImpl(Device)->getPlugin().getBackend() == | ||
backend::ext_oneapi_level_zero; | ||
return Score; | ||
} | ||
|
||
device device_selector::select_device() const { | ||
|
@@ -64,11 +77,12 @@ device device_selector::select_device() const { | |
|
||
// SYCL spec says: "If more than one device receives the high score then | ||
// one of those tied devices will be returned, but which of the devices | ||
// from the tied set is to be returned is not defined". Here we give a | ||
// preference to the device of the preferred BE. | ||
// | ||
// from the tied set is to be returned is not defined". So use the device | ||
// preference score to resolve ties, this is necessary for custom_selectors | ||
// that may not already include device preference in their scoring. | ||
if ((score < dev_score) || | ||
(score == dev_score && isDeviceOfPreferredSyclBe(dev))) { | ||
((score == dev_score) && | ||
(getDevicePreference(*res) < getDevicePreference(dev)))) { | ||
res = &dev; | ||
score = dev_score; | ||
} | ||
|
@@ -97,25 +111,13 @@ device device_selector::select_device() const { | |
/// 1. GPU | ||
/// 2. CPU | ||
/// 3. Host | ||
/// 4. Accelerator | ||
int default_selector::operator()(const device &dev) const { | ||
|
||
int Score = REJECT_DEVICE_SCORE; | ||
|
||
// Give preference to device of SYCL BE. | ||
if (isDeviceOfPreferredSyclBe(dev)) | ||
Score = 50; | ||
|
||
// If SYCL_DEVICE_FILTER is set, filter device gets a high point. | ||
// All unmatched devices should never be selected. | ||
detail::device_filter_list *FilterList = | ||
detail::SYCLConfig<detail::SYCL_DEVICE_FILTER>::get(); | ||
// device::get_devices returns filtered list of devices. | ||
// Keep 1000 for default score when filters were applied. | ||
if (FilterList) | ||
Score = 1000; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this removed? I am not completely sure, but it seems like this tries to ensure that no device is rejected if the user applied a filter. Maybe we could simply change it to a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the history I got the feeling that it was more of a leftover from a time where the default selector was actually using the environment variable to do some filtering, and it felt a bit pointless since if there is a filter all the devices here would start at 1000 score, last PR changing this: #5349 You make a good point about a filtered device potentially being rejected, although I don't think it can happen at the moment since all defined device types are covered and add score, but what would you think about just starting the score for the default selector at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated the patch as I suggested, let me know what you think |
||
// The default selector doesn't reject any devices. | ||
int Score = 0; | ||
|
||
if (dev.get_info<info::device::device_type>() == detail::get_forced_type()) | ||
Score += 1000; | ||
Score += 2000; | ||
|
||
if (dev.is_gpu()) | ||
Score += 500; | ||
|
@@ -132,18 +134,18 @@ int default_selector::operator()(const device &dev) const { | |
if (dev.is_accelerator()) | ||
Score += 75; | ||
|
||
// Add preference score. | ||
Score += getDevicePreference(dev); | ||
|
||
return Score; | ||
} | ||
|
||
int gpu_selector::operator()(const device &dev) const { | ||
int Score = REJECT_DEVICE_SCORE; | ||
|
||
if (dev.is_gpu()) { | ||
// device::get_devices returns filtered list of devices. | ||
Score = 1000; | ||
// Give preference to device of SYCL BE. | ||
if (isDeviceOfPreferredSyclBe(dev)) | ||
Score += 50; | ||
Score += getDevicePreference(dev); | ||
} | ||
return Score; | ||
} | ||
|
@@ -152,12 +154,8 @@ int cpu_selector::operator()(const device &dev) const { | |
int Score = REJECT_DEVICE_SCORE; | ||
|
||
if (dev.is_cpu()) { | ||
// device::get_devices returns filtered list of devices. | ||
Score = 1000; | ||
|
||
// Give preference to device of SYCL BE. | ||
if (isDeviceOfPreferredSyclBe(dev)) | ||
Score += 50; | ||
Score += getDevicePreference(dev); | ||
} | ||
return Score; | ||
} | ||
|
@@ -166,12 +164,8 @@ int accelerator_selector::operator()(const device &dev) const { | |
int Score = REJECT_DEVICE_SCORE; | ||
|
||
if (dev.is_accelerator()) { | ||
// device::get_devices returns filtered list of devices. | ||
Score = 1000; | ||
|
||
// Give preference to device of SYCL BE. | ||
if (isDeviceOfPreferredSyclBe(dev)) | ||
Score += 50; | ||
Score += getDevicePreference(dev); | ||
} | ||
return Score; | ||
} | ||
|
@@ -181,9 +175,7 @@ int host_selector::operator()(const device &dev) const { | |
|
||
if (dev.is_host()) { | ||
Score = 1000; | ||
// Give preference to device of SYCL BE. | ||
if (isDeviceOfPreferredSyclBe(dev)) | ||
Score += 50; | ||
Score += getDevicePreference(dev); | ||
} | ||
return Score; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe instead of running two loops and creating a temporary set, would it be possible to use
std::find
orstd::any_of
on the DeviceImages collection ? That might be easier to read and quicker.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated with a slightly easier to use map and use of
std::any_of