Skip to content

Commit 26ab5ce

Browse files
Changes to select_device_with_aspects
1. Added docstring 2. Rename arguments from "aspect_list", "deny_list" to "required_aspects", "excluded_aspects" 3. Permit aspects to be gives as Python sequences 4. If unsupported aspect is specified, AttributeError is raised as opposed to ValueError 5. ValueError is raised of the requested device is not available. 6. Tests were modified to account for possibility that function invocation may raise ValueError 7. Test was added to test that ValueError error is raised when impossible configuration is requested, like when required_aspects and excluded_aspects sets intersect.
1 parent 6a06099 commit 26ab5ce

File tree

2 files changed

+80
-28
lines changed

2 files changed

+80
-28
lines changed

dpctl/_device_selection.py

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,73 @@
1+
import collections.abc
2+
from itertools import chain
3+
14
from . import SyclDevice, get_devices
25

36

4-
def select_device_with_aspects(aspect_list, deny_list=[]):
5-
check_list = aspect_list + deny_list
6-
for asp in check_list:
7+
def select_device_with_aspects(required_aspects, excluded_aspects=[]):
8+
"""Selects the root :class:`dpctl.SyclDevice` that has the highest
9+
default selector score among devices that have all aspects in the
10+
`required_aspects` list, and do not have any aspects in `excluded_aspects`
11+
list.
12+
13+
Supported
14+
15+
:Example:
16+
.. code-block:: python
17+
18+
import dpctl
19+
# select a GPU that supports double precision
20+
dpctl.select_device_with_aspects(['fp64', 'gpu'])
21+
# select non-custom device with USM shared allocations
22+
dpctl.select_device_with_aspects(
23+
['usm_shared_allocations'], excluded_aspects=['custom'])
24+
"""
25+
if isinstance(required_aspects, str):
26+
required_aspects = [required_aspects]
27+
if isinstance(excluded_aspects, str):
28+
excluded_aspects = [excluded_aspects]
29+
seq = collections.abc.Sequence
30+
input_types_ok = isinstance(required_aspects, seq) and isinstance(
31+
excluded_aspects, seq
32+
)
33+
if not input_types_ok:
34+
raise TypeError(
35+
"Aspects are expected to be Python sequences, "
36+
"e.g. lists, of strings"
37+
)
38+
for asp in chain(required_aspects, excluded_aspects):
739
if type(asp) != str:
840
raise TypeError("The list objects must be of a string type")
941
if not hasattr(SyclDevice, "has_aspect_" + asp):
10-
raise ValueError(f"The {asp} aspect is not supported in dpctl")
42+
raise AttributeError(f"The {asp} aspect is not supported in dpctl")
1143
devs = get_devices()
1244
max_score = 0
1345
selected_dev = None
1446

1547
for dev in devs:
16-
# aspect_status = True
17-
# for asp in aspect_list:
18-
# has_aspect = "dev.has_aspect_" + asp
19-
# if not eval(has_aspect):
20-
# aspect_status = False
21-
# for deny in deny_list:
22-
# has_aspect = "dev.has_aspect_" + deny
23-
# if eval(has_aspect):
24-
# aspect_status = False
2548
aspect_status = all(
26-
(getattr(dev, "has_aspect_" + asp) is True for asp in aspect_list)
49+
(
50+
getattr(dev, "has_aspect_" + asp) is True
51+
for asp in required_aspects
52+
)
2753
)
2854
aspect_status = aspect_status and not (
2955
any(
30-
(getattr(dev, "has_aspect_" + asp) is True for asp in deny_list)
56+
(
57+
getattr(dev, "has_aspect_" + asp) is True
58+
for asp in excluded_aspects
59+
)
3160
)
3261
)
3362
if aspect_status and dev.default_selector_score > max_score:
3463
max_score = dev.default_selector_score
3564
selected_dev = dev
3665

66+
if selected_dev is None:
67+
raise ValueError(
68+
f"Requested device is unavailable: "
69+
f"required_aspects={required_aspects}, "
70+
f"excluded_aspects={excluded_aspects}"
71+
)
72+
3773
return selected_dev

dpctl/tests/test_sycl_device.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ def test_hashing_of_device():
647647
assert device_dict
648648

649649

650-
list_of_valid_aspects = [
650+
list_of_supported_aspects = [
651651
"cpu",
652652
"gpu",
653653
"accelerator",
@@ -664,7 +664,9 @@ def test_hashing_of_device():
664664
"usm_system_allocator",
665665
]
666666

667-
list_of_invalid_aspects = [
667+
# SYCL 2020 spec aspects not presently
668+
# supported in DPC++, and dpctl
669+
list_of_unsupported_aspects = [
668670
"emulated",
669671
"host_debuggable",
670672
"atomic64",
@@ -673,25 +675,39 @@ def test_hashing_of_device():
673675
]
674676

675677

676-
@pytest.fixture(params=list_of_valid_aspects)
677-
def valid_aspects(request):
678+
@pytest.fixture(params=list_of_supported_aspects)
679+
def supported_aspect(request):
678680
return request.param
679681

680682

681-
@pytest.fixture(params=list_of_invalid_aspects)
682-
def invalid_aspects(request):
683+
@pytest.fixture(params=list_of_unsupported_aspects)
684+
def unsupported_aspect(request):
683685
return request.param
684686

685687

686-
def test_valid_aspects(valid_aspects):
687-
dpctl.select_device_with_aspects([valid_aspects])
688+
def test_supported_aspect(supported_aspect):
689+
try:
690+
dpctl.select_device_with_aspects(supported_aspect)
691+
except ValueError:
692+
# ValueError may be raised if no device with
693+
# requested aspect charateristics is available
694+
pass
688695

689696

690-
def test_invalid_aspects(invalid_aspects):
697+
def test_unsupported_aspect(unsupported_aspect):
691698
try:
692-
dpctl.select_device_with_aspects([invalid_aspects])
699+
dpctl.select_device_with_aspects(unsupported_aspect)
693700
raise AttributeError(
694-
f"The {invalid_aspects} aspect is supported in dpctl"
701+
f"The {unsupported_aspect} aspect is now supported in dpctl"
695702
)
696-
except ValueError:
697-
pytest.skip(f"The {invalid_aspects} aspect is not supported in dpctl")
703+
except AttributeError:
704+
pytest.skip(
705+
f"The {unsupported_aspect} aspect is not supported in dpctl"
706+
)
707+
708+
709+
def test_handle_no_device():
710+
with pytest.raises(ValueError):
711+
dpctl.select_device_with_aspects(["gpu", "cpu"])
712+
with pytest.raises(ValueError):
713+
dpctl.select_device_with_aspects("cpu", excluded_aspects="cpu")

0 commit comments

Comments
 (0)