Skip to content

[SYCL] Make device id unique per backend #3611

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

Closed
wants to merge 56 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
e898390
[SYCL] Add device_type into sycl-ls prefix
bso-intel Apr 23, 2021
0bebee4
changed device-id unique per backend
bso-intel Apr 27, 2021
67adc59
filter device with backend-unique id
bso-intel Apr 27, 2021
018e5ad
changed to static_cast
bso-intel Apr 27, 2021
2cd0eae
uppercase device type
bso-intel Apr 28, 2021
4f6d9c4
revert uppercase
bso-intel Apr 28, 2021
dc6d7e0
Update sycl/source/detail/platform_impl.cpp
bso-intel Apr 28, 2021
006bc0e
Update sycl/tools/sycl-ls/sycl-ls.cpp
bso-intel Apr 28, 2021
a8756f1
feedback accommodated
bso-intel Apr 28, 2021
806d7f5
keep last device id in plugin class
bso-intel May 13, 2021
3928f26
Merge remote-tracking branch 'upstream/sycl' into filter
bso-intel May 13, 2021
0a62297
fix clang-format
bso-intel May 14, 2021
24cd067
Update sycl/doc/EnvironmentVariables.md
bso-intel May 14, 2021
4d836dd
keep LastDeviceId per platform
bso-intel May 15, 2021
5a7b3c5
clang-format
bso-intel May 15, 2021
e0b6c40
Update sycl/doc/EnvironmentVariables.md
bso-intel May 18, 2021
8179ebd
Merge remote-tracking branch 'upstream/sycl' into filter
bso-intel May 21, 2021
7a1b614
Merge remote-tracking branch 'upstream/sycl' into filter
bso-intel Jun 21, 2021
cfdefd0
refactored device cache
bso-intel Jun 21, 2021
5c85960
fixed clang-format
bso-intel Jun 21, 2021
8f6a09b
shared_ptr in global device cache
bso-intel Jun 28, 2021
e6a64a1
merge conflict
bso-intel Jun 29, 2021
faab5a7
removed debugging print
bso-intel Jun 29, 2021
c096a7b
fix clang-format
bso-intel Jun 29, 2021
6e906eb
Update sycl/source/detail/pi.cpp
bso-intel Jun 30, 2021
54876fc
Update sycl/source/detail/pi.cpp
bso-intel Jun 30, 2021
70c415b
Update sycl/source/detail/pi.cpp
bso-intel Jun 30, 2021
5d9f900
Update sycl/source/detail/pi.cpp
bso-intel Jun 30, 2021
f650fae
respond to feedback
bso-intel Jun 30, 2021
6bfee42
Merge branch 'filter' of https://github.com/bso-intel/llvm into filter
bso-intel Jun 30, 2021
6ea7d39
additional typo
bso-intel Jun 30, 2021
257b060
Merge remote-tracking branch 'upstream/sycl' into filter
bso-intel Jun 30, 2021
4b7b0d1
fix format
bso-intel Jun 30, 2021
10f7893
fix windows teardown
bso-intel Jul 1, 2021
7216168
fix clang-format
bso-intel Jul 1, 2021
d1f572d
fix declspec
bso-intel Jul 1, 2021
b19f969
use sycl export
bso-intel Jul 2, 2021
028cebc
Update sycl/source/detail/pi.cpp
bso-intel Jul 6, 2021
7d5a1d5
Merge remote-tracking branch 'upstream/sycl' into filter
bso-intel Jul 6, 2021
ad35188
respond to feedback
bso-intel Jul 6, 2021
3e1c91d
merge upstream
bso-intel Jul 16, 2021
ef19467
fix clang-format
bso-intel Jul 16, 2021
eadb848
merge two caches for device/platform
bso-intel Jul 17, 2021
317387f
clang-format
bso-intel Jul 17, 2021
1f9be1d
Merge remote-tracking branch 'upstream/sycl' into filter
bso-intel Jul 17, 2021
8751ad8
fix deadlock
bso-intel Jul 17, 2021
e8be632
optimize device_impl
bso-intel Jul 18, 2021
e8a26da
trial revert of windows fix
bso-intel Jul 20, 2021
d3b9cda
tokenize filter
bso-intel Jul 24, 2021
1dc38df
try to disable cleaning up device cache
bso-intel Jul 25, 2021
d2e967a
revert
bso-intel Jul 25, 2021
cc428ff
Update sycl/source/detail/device_filter.cpp
bso-intel Jul 26, 2021
0a4c4fc
Update sycl/source/detail/device_filter.cpp
bso-intel Jul 26, 2021
ffa3813
feedback
bso-intel Jul 26, 2021
19de5f4
trial tests
bso-intel Jul 29, 2021
7f02fc3
try Windows shutdown
bso-intel Jul 31, 2021
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
28 changes: 14 additions & 14 deletions sycl/doc/EnvironmentVariables.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,25 @@ subject to change. Do not rely on these variables in production code.

This environment variable limits the SYCL RT to use only a subset of the system's devices. Setting this environment variable affects all of the device query functions (`platform::get_devices()` and `platform::get_platforms()`) and all of the device selectors.

The value of this environment variable is a comma separated list of filters, where each filter is a triple of the form "`backend:device_type:device_num`" (without the quotes). Each element of the triple is optional, but each filter must have at least one value. Possible values of "backend" are:
- host
The value of this environment variable is a comma separated list of filters, where each filter is a triple of the form "`backend`:`device_type`:`device_num`" (without the quotes). Each element of the triple is optional, but each filter must have at least one value. Possible values of `backend` are:
- `host`
- `level_zero`
- opencl
- cuda
- \*
- `opencl`
- `cuda`
- `*`

Possible values of "`device_type`" are:
- host
- cpu
- gpu
- acc
- \*
Possible values of `device_type` are:
- `host`
- `cpu`
- `gpu`
- `acc`
- `*`

`Device_num` is an integer that indexes the enumeration of devices from the sycl-ls utility tool, where the first device in that enumeration has index zero in each backend. For example, `SYCL_DEVICE_FILTER`=2 will return all devices with index '2' from all different backends. If multiple devices satisfy this device number (e.g., GPU and CPU devices can be assigned device number '2'), then default_selector will choose the device with the highest heuristic point.
`device_num` is an integer that indexes the enumeration of devices from the sycl-ls utility tool, where the first device in that enumeration has index zero in each backend. For example, `SYCL_DEVICE_FILTER=2` will return all devices with index '2' from all different backends. If multiple devices satisfy this device number (e.g., GPU and CPU devices can be assigned device number '2'), then default_selector will choose the device with the highest heuristic point. When `SYCL_DEVICE_ALLOWLIST` is set, it is applied before enumerating devices and affects `device_num` values.

Assuming a filter has all three elements of the triple, it selects only those devices that come from the given backend, have the specified device type, AND have the given device index. If more than one filter is specified, the RT is restricted to the union of devices selected by all filters. The RT does not include the "host" backend and the host device automatically unless one of the filters explicitly specifies the "host" device type. Therefore, `SYCL_DEVICE_FILTER`=host should be set to enforce SYCL to use the host device only.
Assuming a filter has all three elements of the triple, it selects only those devices that come from the given backend, have the specified device type, AND have the given device index. If more than one filter is specified, the RT is restricted to the union of devices selected by all filters. The RT does not include the `host` backend and the `host` device automatically unless one of the filters explicitly specifies the `host` device type. Therefore, `SYCL_DEVICE_FILTER=host` should be set to enforce SYCL to use the `host` device only.

Note that all device selectors will throw an exception if the filtered list of devices does not include a device that satisfies the selector. For instance, `SYCL_DEVICE_FILTER`=cpu,level_zero will cause host_selector() to throw an exception. `SYCL_DEVICE_FILTER` also limits loading only specified plugins into the SYCL RT. In particular, `SYCL_DEVICE_FILTER`=level_zero will cause the cpu_selector to throw an exception since SYCL RT will only load the level_zero backend which does not support any CPU devices at this time. When multiple devices satisfy the filter (e..g, `SYCL_DEVICE_FILTER`=gpu), only one of them will be selected.
Note that all device selectors will throw an exception if the filtered list of devices does not include a device that satisfies the selector. For instance, `SYCL_DEVICE_FILTER=cpu,level_zero` will cause `host_selector()` to throw an exception. `SYCL_DEVICE_FILTER` also limits loading only specified plugins into the SYCL RT. In particular, `SYCL_DEVICE_FILTER=level_zero` will cause the `cpu_selector` to throw an exception since SYCL RT will only load the `level_zero` backend which does not support any CPU devices at this time. When multiple devices satisfy the filter (e..g, `SYCL_DEVICE_FILTER=gpu`), only one of them will be selected.

### `SYCL_PRINT_EXECUTION_GRAPH` Options

Expand Down
3 changes: 3 additions & 0 deletions sycl/include/CL/sycl/detail/device_filter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ inline std::ostream &operator<<(std::ostream &Out,
return Out;
}

std::vector<std::string> tokenize(const std::string &Filter,
const std::string &Delim);

} // namespace detail
} // namespace sycl
} // __SYCL_INLINE_NAMESPACE(cl)
4 changes: 2 additions & 2 deletions sycl/source/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,11 @@ static const std::array<std::pair<std::string, info::device_type>, 5>

// Array is used by SYCL_DEVICE_FILTER and SYCL_DEVICE_ALLOWLIST
static const std::array<std::pair<std::string, backend>, 6> SyclBeMap = {
{{"host", backend::host},
{"opencl", backend::opencl},
{{"opencl", backend::opencl},
{"level_zero", backend::level_zero},
{"cuda", backend::cuda},
{"rocm", backend::rocm},
{"host", backend::host},
{"*", backend::all}}};

template <> class SYCLConfig<SYCL_DEVICE_FILTER> {
Expand Down
56 changes: 36 additions & 20 deletions sycl/source/detail/device_filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,60 +17,76 @@ __SYCL_INLINE_NAMESPACE(cl) {
namespace sycl {
namespace detail {

std::vector<std::string> tokenize(const std::string &Filter,
const std::string &Delim) {
std::vector<std::string> Tokens;
size_t Pos = 0;
std::string Input = Filter;
std::string Tok;

while ((Pos = Input.find(Delim)) != std::string::npos) {
Tok = Input.substr(0, Pos);
Input.erase(0, Pos + Delim.length());

if (!Tok.empty()) {
Tokens.push_back(std::move(Tok));
}
}

// Add remainder
if (!Input.empty())
Tokens.push_back(std::move(Input));

return Tokens;
}

device_filter::device_filter(const std::string &FilterString) {
size_t Cursor = 0;
size_t ColonPos = 0;
auto findElement = [&](auto Element) {
size_t Found = FilterString.find(Element.first, Cursor);
std::vector<std::string> Tokens = tokenize(FilterString, ":");
size_t I = 0;

auto FindElement = [&](auto Element) {
size_t Found = Tokens[I].find(Element.first);
if (Found == std::string::npos)
return false;
Cursor = Found;
return true;
};

// Handle the optional 1st field of the filter, backend
// Check if the first entry matches with a known backend type
auto It =
std::find_if(std::begin(SyclBeMap), std::end(SyclBeMap), findElement);
std::find_if(std::begin(SyclBeMap), std::end(SyclBeMap), FindElement);
// If no match is found, set the backend type backend::all
// which actually means 'any backend' will be a match.
if (It == SyclBeMap.end())
Backend = backend::all;
else {
Backend = It->second;
ColonPos = FilterString.find(":", Cursor);
if (ColonPos != std::string::npos)
Cursor = ColonPos + 1;
else
Cursor = Cursor + It->first.size();
I++;
}

// Handle the optional 2nd field of the filter - device type.
// Check if the 2nd entry matches with any known device type.
if (Cursor >= FilterString.size()) {
if (I >= Tokens.size()) {
DeviceType = info::device_type::all;
} else {
auto Iter = std::find_if(std::begin(SyclDeviceTypeMap),
std::end(SyclDeviceTypeMap), findElement);
std::end(SyclDeviceTypeMap), FindElement);
// If no match is found, set device_type 'all',
// which actually means 'any device_type' will be a match.
if (Iter == SyclDeviceTypeMap.end())
DeviceType = info::device_type::all;
else {
DeviceType = Iter->second;
ColonPos = FilterString.find(":", Cursor);
if (ColonPos != std::string::npos)
Cursor = ColonPos + 1;
else
Cursor = Cursor + Iter->first.size();
I++;
}
}

// Handle the optional 3rd field of the filter, device number
// Try to convert the remaining string to an integer.
// If succeessful, the converted integer is the desired device num.
if (Cursor < FilterString.size()) {
if (I < Tokens.size()) {
try {
DeviceNum = stoi(FilterString.substr(Cursor));
DeviceNum = stoi(Tokens[I]);
HasDeviceNum = true;
} catch (...) {
std::string Message =
Expand Down
27 changes: 2 additions & 25 deletions sycl/source/detail/filter_selector_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,12 @@ namespace sycl {
namespace ONEAPI {
namespace detail {

std::vector<std::string> tokenize(const std::string &Filter,
const std::string &Delim) {
std::vector<std::string> Tokens;
size_t Pos = 0;
std::string Input = Filter;
std::string Tok;

while ((Pos = Input.find(Delim)) != std::string::npos) {
Tok = Input.substr(0, Pos);
Input.erase(0, Pos + Delim.length());

if (!Tok.empty()) {
Tokens.push_back(std::move(Tok));
}
}

// Add remainder
if (!Input.empty())
Tokens.push_back(std::move(Input));

return Tokens;
}

filter create_filter(const std::string &Input) {
filter Result;
constexpr auto Error = "Invalid filter string! Valid strings conform to "
"BE:DeviceType:DeviceNum, where any are optional";

std::vector<std::string> Tokens = tokenize(Input, ":");
std::vector<std::string> Tokens = sycl::detail::tokenize(Input, ":");
std::regex IntegerExpr("[[:digit:]]+");

// There should only be up to 3 tokens.
Expand Down Expand Up @@ -106,7 +83,7 @@ filter create_filter(const std::string &Input) {

filter_selector_impl::filter_selector_impl(const std::string &Input)
: mFilters(), mRanker(), mNumDevicesSeen(0), mMatchFound(false) {
std::vector<std::string> Filters = detail::tokenize(Input, ",");
std::vector<std::string> Filters = sycl::detail::tokenize(Input, ",");
mNumTotalDevices = device::get_devices().size();

for (const std::string &Filter : Filters) {
Expand Down
7 changes: 4 additions & 3 deletions sycl/source/detail/global_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ ProgramManager &GlobalHandler::getProgramManager() {

Sync &GlobalHandler::getSync() { return getOrCreate(MSync); }

std::vector<PlatformImplPtr> &GlobalHandler::getPlatformCache() {
return getOrCreate(MPlatformCache);
std::map<PlatformImplPtr, std::vector<DeviceImplPtr>> &
GlobalHandler::getPlatformDeviceCache() {
return getOrCreate(MPlatformDeviceCache);
}

std::mutex &GlobalHandler::getPlatformMapMutex() {
Expand All @@ -79,7 +80,7 @@ void shutdown() {
// First, release resources, that may access plugins.
GlobalHandler::instance().MScheduler.Inst.reset(nullptr);
GlobalHandler::instance().MProgramManager.Inst.reset(nullptr);
GlobalHandler::instance().MPlatformCache.Inst.reset(nullptr);
GlobalHandler::instance().MPlatformDeviceCache.Inst.reset(nullptr);

// Call to GlobalHandler::instance().getPlugins() initializes plugins. If
// user application has loaded SYCL runtime, and never called any APIs,
Expand Down
9 changes: 7 additions & 2 deletions sycl/source/detail/global_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <CL/sycl/detail/spinlock.hpp>
#include <CL/sycl/detail/util.hpp>

#include <map>
#include <memory>

__SYCL_INLINE_NAMESPACE(cl) {
Expand All @@ -22,8 +23,10 @@ class ProgramManager;
class Sync;
class plugin;
class device_filter_list;
class device_impl;

using PlatformImplPtr = std::shared_ptr<platform_impl>;
using DeviceImplPtr = std::shared_ptr<device_impl>;

/// Wrapper class for global data structures with non-trivial destructors.
///
Expand Down Expand Up @@ -51,7 +54,8 @@ class GlobalHandler {
Scheduler &getScheduler();
ProgramManager &getProgramManager();
Sync &getSync();
std::vector<PlatformImplPtr> &getPlatformCache();
std::map<PlatformImplPtr, std::vector<DeviceImplPtr>> &
getPlatformDeviceCache();
std::mutex &getPlatformMapMutex();
std::mutex &getFilterMutex();
std::vector<plugin> &getPlugins();
Expand All @@ -77,7 +81,8 @@ class GlobalHandler {
InstWithLock<Scheduler> MScheduler;
InstWithLock<ProgramManager> MProgramManager;
InstWithLock<Sync> MSync;
InstWithLock<std::vector<PlatformImplPtr>> MPlatformCache;
InstWithLock<std::map<PlatformImplPtr, std::vector<DeviceImplPtr>>>
MPlatformDeviceCache;
InstWithLock<std::mutex> MPlatformMapMutex;
InstWithLock<std::mutex> MFilterMutex;
InstWithLock<std::vector<plugin>> MPlugins;
Expand Down
Loading