Skip to content

Commit f432fe5

Browse files
Python examples expanded:
Device selection examples added Sub-device creation examples added
1 parent d1b097e commit f432fe5

File tree

2 files changed

+204
-0
lines changed

2 files changed

+204
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Data Parallel Control (dpctl)
2+
#
3+
# Copyright 2020-2021 Intel Corporation
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
"""Examples illustrating SYCL device selection features provided by dpctl.
18+
"""
19+
20+
import dpctl
21+
22+
23+
def print_device(d):
24+
if type(d) is not dpctl.SyclDevice:
25+
raise ValueError
26+
print("Name: ", d.name)
27+
print("Vendor: ", d.vendor)
28+
print("Driver version: ", d.driver_version)
29+
print("Backend: ", d.backend)
30+
print("Max EU: ", d.max_compute_units)
31+
32+
33+
def create_default_device():
34+
"""
35+
Create default SyclDevice using `cl::sycl::default_selector`.
36+
37+
Device created can be influenced by environment variable
38+
SYCL_DEVICE_FILTER, which determines SYCL devices seen by the
39+
SYCL runtime.
40+
"""
41+
d1 = dpctl.SyclDevice()
42+
d2 = dpctl.select_default_device()
43+
assert d1 == d2
44+
print_device(d1)
45+
return d1
46+
47+
48+
def create_gpu_device():
49+
"""
50+
Create a GPU device.
51+
52+
Device created can be influenced by environment variable
53+
SYCL_DEVICE_FILTER, which determines SYCL devices seen by the
54+
SYCL runtime.
55+
"""
56+
d1 = dpctl.SyclDevice("gpu")
57+
d2 = dpctl.select_gpu_device()
58+
assert d1 == d2
59+
print_device(d1)
60+
return d1
61+
62+
63+
def create_gpu_device_if_present():
64+
"""
65+
Select from union of two selections using default_selector.
66+
If a GPU device is available, it will be selected, if not,
67+
a CPU device will be selected, if available, otherwise an error
68+
will be raised.
69+
70+
Device created can be influenced by environment variable
71+
SYCL_DEVICE_FILTER, which determines SYCL devices seen by the
72+
SYCL runtime.
73+
"""
74+
d = dpctl.SyclDevice("gpu,cpu")
75+
print("Selected " + ("GPU" if d.is_gpu else "CPU") + " device")
76+
77+
78+
def custom_select_device():
79+
"""
80+
Programmatically select among available devices.
81+
82+
Device created can be influenced by environment variable
83+
SYCL_DEVICE_FILTER, which determines SYCL devices seen by the
84+
SYCL runtime.
85+
"""
86+
# select devices that support half-precision computation
87+
devs = [d for d in dpctl.get_devices() if d.has_aspect_fp16]
88+
# choose the device with highest default_selector score
89+
max_score = 0
90+
selected_dev = None
91+
for d in devs:
92+
if d.default_selector_score > max_score:
93+
max_score = d.default_selector_score
94+
selected_dev = d
95+
if selected_dev:
96+
print_device(selected_dev)
97+
return selected_dev

examples/python/subdevices.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Data Parallel Control (dpctl)
2+
#
3+
# Copyright 2020-2021 Intel Corporation
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
import dpctl
18+
import dpctl.memory
19+
20+
21+
def is_root_device(d):
22+
"""
23+
Returns True if d is an instance of SyclDevice that does not
24+
have a parent_device, or False otherwise.
25+
"""
26+
if not isinstance(d, dpctl.SyclDevice):
27+
return False
28+
# d.parent_device is None for a root device,
29+
# or a SyclDevice object representing the parent device
30+
# for a sub-device
31+
return d.parent_device is None
32+
33+
34+
def subdivide_root_cpu_device():
35+
"""
36+
Create root CPU device, and equally partition it
37+
into smaller CPU devices 4 execution units each,
38+
and then further parition those subdevice into
39+
smaller sub-devices
40+
"""
41+
cpu_d = dpctl.SyclDevice("cpu")
42+
print(
43+
"cpu_d is "
44+
+ ("a root device." if is_root_device(cpu_d) else "not a root device.")
45+
)
46+
sub_devs = cpu_d.create_sub_devices(partition=4)
47+
print("Sub-device #EU: ", [d.max_compute_units for d in sub_devs])
48+
print("Sub-device is_root: ", [is_root_device(d) for d in sub_devs])
49+
print(
50+
"Sub-device parent is what we expected: ",
51+
[d.parent_device == cpu_d for d in sub_devs],
52+
)
53+
54+
# Further partition each sub-device
55+
subsub_dev_eu_count = [
56+
[sd.max_compute_units for sd in d.create_sub_devices(partition=(1, 3))]
57+
for d in sub_devs
58+
]
59+
print("Sub-sub-device #EU: ", subsub_dev_eu_count)
60+
61+
62+
def subdivide_by_affinity(affinity="numa"):
63+
"""
64+
Create sub-devices partitioning by affinity.
65+
"""
66+
cpu_d = dpctl.SyclDevice("cpu")
67+
sub_devs = cpu_d.create_sub_devices(partition=affinity)
68+
return sub_devs
69+
70+
71+
def create_subdevice_queue():
72+
"""
73+
Partition a CPU sycl device into sub-devices.
74+
Create a multi-device sycl context.
75+
76+
"""
77+
cpu_d = dpctl.SyclDevice("cpu")
78+
cpu_count = cpu_d.max_compute_units
79+
sub_devs = cpu_d.create_sub_devices(partition=cpu_count // 2)
80+
multidevice_ctx = dpctl.SyclContext(sub_devs)
81+
# create a SyclQueue for each sub-device, using commont
82+
# multi-device context
83+
q0, q1 = [dpctl.SyclQueue(multidevice_ctx, d) for d in sub_devs]
84+
# for each sub-device allocate 26 bytes
85+
m0 = dpctl.memory.MemoryUSMDevice(26, queue=q0)
86+
m1 = dpctl.memory.MemoryUSMDevice(26, queue=q1)
87+
# populate m0 with host data of spaces
88+
hostmem = bytearray(b" " * 26)
89+
# copy spaces into m1
90+
m1.copy_from_host(hostmem)
91+
for i in range(26):
92+
hostmem[i] = ord("a") + i
93+
# copy character sequence into m0
94+
m0.copy_from_host(hostmem)
95+
# from from m0 to m1. Due to using multi-device context,
96+
# copying can be done directly
97+
m1.copy_from_device(m0)
98+
return bytes(m1.copy_to_host())
99+
100+
101+
if __name__ == "__main__":
102+
print("")
103+
print("Executing subdivide_root_cpu_device:")
104+
subdivide_root_cpu_device()
105+
print("")
106+
print("Exectuting create_subdevice_queue:")
107+
print(create_subdevice_queue())

0 commit comments

Comments
 (0)