Skip to content

Commit 7aa6fb7

Browse files
authored
Merge pull request #1992 from IntelPython/get-devices-from-sycl-platform
Add `get_devices` method to `dpctl.SyclPlatform` class
2 parents 3fb408b + d166366 commit 7aa6fb7

11 files changed

+228
-17
lines changed

dpctl/_backend.pxd

+2
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ cdef extern from "syclinterface/dpctl_sycl_platform_interface.h":
313313
cdef DPCTLPlatformVectorRef DPCTLPlatform_GetPlatforms()
314314
cdef DPCTLSyclContextRef DPCTLPlatform_GetDefaultContext(
315315
const DPCTLSyclPlatformRef)
316+
cdef DPCTLDeviceVectorRef DPCTLPlatform_GetDevices(
317+
const DPCTLSyclPlatformRef PRef, _device_type DTy)
316318

317319

318320
cdef extern from "syclinterface/dpctl_sycl_context_interface.h":

dpctl/_sycl_device_factory.pyx

+6-6
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,15 @@ cpdef list get_devices(backend=backend_type.all, device_type=device_type_t.all):
154154
``backend`` in addition to only ``device_type``.
155155
156156
Args:
157-
backend (optional):
157+
backend (str, :class:`dpctl.backend_type`, optional):
158158
A :class:`dpctl.backend_type` enum value or a string that
159159
specifies a SYCL backend. Currently, accepted values are: "cuda",
160160
"hip", "opencl", "level_zero", or "all".
161161
Default: ``dpctl.backend_type.all``.
162-
device_type (optional):
162+
device_type (str, :class:`dpctl.device_type`, optional):
163163
A :class:`dpctl.device_type` enum value or a string that
164164
specifies a SYCL device type. Currently, accepted values are:
165-
"gpu", "cpu", "accelerator", "host", or "all".
165+
"gpu", "cpu", "accelerator", or "all".
166166
Default: ``dpctl.device_type.all``.
167167
Returns:
168168
list:
@@ -210,15 +210,15 @@ cpdef int get_num_devices(
210210
:class:`dpctl.device_type` and :class:`dpctl.backend_type`.
211211
212212
Args:
213-
backend (optional):
213+
backend (str, :class:`dpctl.backend_type`, optional):
214214
A :class:`dpctl.backend_type` enum value or a string that
215215
specifies a SYCL backend. Currently, accepted values are: "cuda",
216216
"hip", "opencl", "level_zero", or "all".
217217
Default: ``dpctl.backend_type.all``.
218-
device_type (optional):
218+
device_type (str, :class:`dpctl.device_type`, optional):
219219
A :class:`dpctl.device_type` enum value or a string that
220220
specifies a SYCL device type. Currently, accepted values are:
221-
"gpu", "cpu", "accelerator", "host", or "all".
221+
"gpu", "cpu", "accelerator", or "all".
222222
Default: ``dpctl.device_type.all``.
223223
Returns:
224224
int:

dpctl/_sycl_platform.pyx

+82
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ from libcpp cimport bool
2626
from ._backend cimport ( # noqa: E211
2727
DPCTLCString_Delete,
2828
DPCTLDeviceSelector_Delete,
29+
DPCTLDeviceVector_Delete,
30+
DPCTLDeviceVector_GetAt,
31+
DPCTLDeviceVector_Size,
32+
DPCTLDeviceVectorRef,
2933
DPCTLFilterSelector_Create,
3034
DPCTLPlatform_AreEq,
3135
DPCTLPlatform_Copy,
@@ -34,6 +38,7 @@ from ._backend cimport ( # noqa: E211
3438
DPCTLPlatform_Delete,
3539
DPCTLPlatform_GetBackend,
3640
DPCTLPlatform_GetDefaultContext,
41+
DPCTLPlatform_GetDevices,
3742
DPCTLPlatform_GetName,
3843
DPCTLPlatform_GetPlatforms,
3944
DPCTLPlatform_GetVendor,
@@ -46,17 +51,21 @@ from ._backend cimport ( # noqa: E211
4651
DPCTLPlatformVector_Size,
4752
DPCTLPlatformVectorRef,
4853
DPCTLSyclContextRef,
54+
DPCTLSyclDeviceRef,
4955
DPCTLSyclDeviceSelectorRef,
5056
DPCTLSyclPlatformRef,
5157
_backend_type,
58+
_device_type,
5259
)
5360

5461
import warnings
5562

5663
from ._sycl_context import SyclContextCreationError
5764
from .enum_types import backend_type
65+
from .enum_types import device_type as device_type_t
5866

5967
from ._sycl_context cimport SyclContext
68+
from ._sycl_device cimport SyclDevice
6069

6170
__all__ = [
6271
"get_platforms",
@@ -366,6 +375,79 @@ cdef class SyclPlatform(_SyclPlatform):
366375
"""
367376
return DPCTLPlatform_Hash(self._platform_ref)
368377

378+
def get_devices(self, device_type=device_type_t.all):
379+
"""
380+
Returns the list of :class:`dpctl.SyclDevice` objects associated with
381+
:class:`dpctl.SyclPlatform` instance selected based on
382+
the given :class:`dpctl.device_type`.
383+
384+
Args:
385+
device_type (str, :class:`dpctl.device_type`, optional):
386+
A :class:`dpctl.device_type` enum value or a string that
387+
specifies a SYCL device type. Currently, accepted values are:
388+
"gpu", "cpu", "accelerator", or "all", and their equivalent
389+
``dpctl.device_type`` enumerators.
390+
Default: ``dpctl.device_type.all``.
391+
392+
Returns:
393+
list:
394+
A :obj:`list` of :class:`dpctl.SyclDevice` objects
395+
that belong to this platform.
396+
397+
Raises:
398+
TypeError:
399+
If `device_type` is not a string or :class:`dpctl.device_type`
400+
enum.
401+
ValueError:
402+
If the ``DPCTLPlatform_GetDevices`` call returned
403+
``NULL`` instead of a ``DPCTLDeviceVectorRef`` object.
404+
"""
405+
cdef _device_type DTy = _device_type._ALL_DEVICES
406+
cdef DPCTLDeviceVectorRef DVRef = NULL
407+
cdef size_t num_devs
408+
cdef size_t i
409+
cdef DPCTLSyclDeviceRef DRef
410+
411+
if isinstance(device_type, str):
412+
dty_str = device_type.strip().lower()
413+
if dty_str == "accelerator":
414+
DTy = _device_type._ACCELERATOR
415+
elif dty_str == "all":
416+
DTy = _device_type._ALL_DEVICES
417+
elif dty_str == "cpu":
418+
DTy = _device_type._CPU
419+
elif dty_str == "gpu":
420+
DTy = _device_type._GPU
421+
else:
422+
DTy = _device_type._UNKNOWN_DEVICE
423+
elif isinstance(device_type, device_type_t):
424+
if device_type == device_type_t.all:
425+
DTy = _device_type._ALL_DEVICES
426+
elif device_type == device_type_t.accelerator:
427+
DTy = _device_type._ACCELERATOR
428+
elif device_type == device_type_t.cpu:
429+
DTy = _device_type._CPU
430+
elif device_type == device_type_t.gpu:
431+
DTy = _device_type._GPU
432+
else:
433+
DTy = _device_type._UNKNOWN_DEVICE
434+
else:
435+
raise TypeError(
436+
"device type should be specified as a str or an "
437+
"``enum_types.device_type``."
438+
)
439+
DVRef = DPCTLPlatform_GetDevices(self.get_platform_ref(), DTy)
440+
if (DVRef is NULL):
441+
raise ValueError("Internal error: NULL device vector encountered")
442+
num_devs = DPCTLDeviceVector_Size(DVRef)
443+
devices = []
444+
for i in range(num_devs):
445+
DRef = DPCTLDeviceVector_GetAt(DVRef, i)
446+
devices.append(SyclDevice._create(DRef))
447+
DPCTLDeviceVector_Delete(DVRef)
448+
449+
return devices
450+
369451

370452
def lsplatform(verbosity=0):
371453
"""

dpctl/tests/test_sycl_device_factory.py

-4
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ def string_to_device_type(dty_str):
5151
return dty.accelerator
5252
elif dty_str == "cpu":
5353
return dty.cpu
54-
elif dty_str == "host":
55-
return dty.host
5654
elif dty_str == "gpu":
5755
return dty.gpu
5856

@@ -62,8 +60,6 @@ def string_to_backend_type(bty_str):
6260
return bty.cuda
6361
elif bty_str == "hip":
6462
return bty.hip
65-
elif bty_str == "host":
66-
return bty.host
6763
elif bty_str == "level_zero":
6864
return bty.level_zero
6965
elif bty_str == "opencl":

dpctl/tests/test_sycl_platform.py

+47
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import pytest
2323

2424
import dpctl
25+
from dpctl import device_type
2526

2627
from .helper import has_sycl_platforms
2728

@@ -212,3 +213,49 @@ def test_get_platforms():
212213
assert has_sycl_platforms()
213214
except Exception:
214215
pytest.fail("Encountered an exception inside get_platforms().")
216+
217+
218+
def test_platform_get_devices():
219+
platforms = dpctl.get_platforms()
220+
if platforms:
221+
for p in platforms:
222+
assert len(p.get_devices())
223+
else:
224+
pytest.skip("No platforms available")
225+
226+
227+
def _str_device_type_to_enum(dty):
228+
if dty == "accelerator":
229+
return device_type.accelerator
230+
elif dty == "cpu":
231+
return device_type.cpu
232+
elif dty == "gpu":
233+
return device_type.gpu
234+
235+
236+
def test_platform_get_devices_str_device_type():
237+
platforms = dpctl.get_platforms()
238+
dtys = ["accelerator", "all", "cpu", "gpu"]
239+
if platforms:
240+
for p in platforms:
241+
for dty in dtys:
242+
devices = p.get_devices(device_type=dty)
243+
if len(devices):
244+
dty_enum = _str_device_type_to_enum(dty)
245+
assert (d.device_type == dty_enum for d in devices)
246+
247+
248+
def test_platform_get_devices_enum_device_type():
249+
platforms = dpctl.get_platforms()
250+
dtys = [
251+
device_type.accelerator,
252+
device_type.all,
253+
device_type.cpu,
254+
device_type.gpu,
255+
]
256+
if platforms:
257+
for p in platforms:
258+
for dty in dtys:
259+
devices = p.get_devices(device_type=dty)
260+
if len(devices):
261+
assert (d.device_type == dty for d in devices)

libsyclinterface/helper/source/dpctl_utils_helper.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@ info::device_type DPCTL_StrToDeviceType(const std::string &devTyStr)
7373
else if (devTyStr == "custom") {
7474
devTy = info::device_type::custom;
7575
}
76-
else if (devTyStr == "host") {
77-
devTy = info::device_type::host;
78-
}
7976
else {
8077
// \todo handle the error
8178
throw std::runtime_error("Unknown device type.");

libsyclinterface/include/syclinterface/dpctl_sycl_device_manager.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ DPCTL_API
145145
size_t DPCTLDeviceMgr_GetNumDevices(int device_identifier);
146146

147147
/*!
148-
* @brief Prints out the info::deivice attributes for the device that are
148+
* @brief Prints out the info::device attributes for the device that are
149149
* currently supported by dpctl.
150150
*
151151
* @param DRef A #DPCTLSyclDeviceRef opaque pointer.

libsyclinterface/include/syclinterface/dpctl_sycl_platform_interface.h

+16-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "Support/ExternC.h"
3030
#include "Support/MemOwnershipAttrs.h"
3131
#include "dpctl_data_types.h"
32+
#include "dpctl_sycl_device_manager.h"
3233
#include "dpctl_sycl_enum_types.h"
3334
#include "dpctl_sycl_platform_manager.h"
3435
#include "dpctl_sycl_types.h"
@@ -176,6 +177,20 @@ DPCTLPlatform_GetDefaultContext(__dpctl_keep const DPCTLSyclPlatformRef PRef);
176177
* @ingroup PlatformInterface
177178
*/
178179
DPCTL_API
179-
size_t DPCTLPlatform_Hash(__dpctl_keep DPCTLSyclPlatformRef PRef);
180+
size_t DPCTLPlatform_Hash(__dpctl_keep const DPCTLSyclPlatformRef PRef);
181+
182+
/*!
183+
* @brief Returns a vector of devices associated with sycl::platform referenced
184+
* by DPCTLSyclPlatformRef object.
185+
*
186+
* @param PRef The DPCTLSyclPlatformRef pointer.
187+
* @param DTy A DPCTLSyclDeviceType enum value.
188+
* @return A DPCTLDeviceVectorRef with devices associated with given PRef.
189+
* @ingroup PlatformInterface
190+
*/
191+
DPCTL_API
192+
__dpctl_give DPCTLDeviceVectorRef
193+
DPCTLPlatform_GetDevices(__dpctl_keep const DPCTLSyclPlatformRef PRef,
194+
DPCTLSyclDeviceType DTy);
180195

181196
DPCTL_C_EXTERN_C_END

libsyclinterface/source/dpctl_sycl_platform_interface.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "dpctl_device_selection.hpp"
3030
#include "dpctl_error_handlers.h"
3131
#include "dpctl_string_utils.hpp"
32+
#include "dpctl_sycl_enum_types.h"
3233
#include "dpctl_sycl_type_casters.hpp"
3334
#include "dpctl_utils_helper.h"
3435
#include <iomanip>
@@ -269,3 +270,49 @@ size_t DPCTLPlatform_Hash(__dpctl_keep const DPCTLSyclPlatformRef PRef)
269270
return 0;
270271
}
271272
}
273+
274+
__dpctl_give DPCTLDeviceVectorRef
275+
DPCTLPlatform_GetDevices(__dpctl_keep const DPCTLSyclPlatformRef PRef,
276+
DPCTLSyclDeviceType DTy)
277+
{
278+
auto P = unwrap<platform>(PRef);
279+
if (!P) {
280+
error_handler("Cannot retrieve devices from DPCTLSyclPlatformRef as "
281+
"input is a nullptr.",
282+
__FILE__, __func__, __LINE__);
283+
return nullptr;
284+
}
285+
286+
using vecTy = std::vector<DPCTLSyclDeviceRef>;
287+
vecTy *DevicesVectorPtr = nullptr;
288+
try {
289+
DevicesVectorPtr = new vecTy();
290+
} catch (std::exception const &e) {
291+
delete DevicesVectorPtr;
292+
error_handler(e, __FILE__, __func__, __LINE__);
293+
return nullptr;
294+
}
295+
296+
// handle unknown device
297+
// custom and automatic are also treated as unknown
298+
// as DPC++ would normally treat as `all`
299+
// see CMPLRLLVM-65826
300+
if (DTy == DPCTLSyclDeviceType::DPCTL_UNKNOWN_DEVICE) {
301+
return wrap<vecTy>(DevicesVectorPtr);
302+
}
303+
304+
try {
305+
auto SyclDTy = DPCTL_DPCTLDeviceTypeToSyclDeviceType(DTy);
306+
auto Devices = P->get_devices(SyclDTy);
307+
DevicesVectorPtr->reserve(Devices.size());
308+
for (const auto &Dev : Devices) {
309+
DevicesVectorPtr->emplace_back(
310+
wrap<device>(new device(std::move(Dev))));
311+
}
312+
return wrap<vecTy>(DevicesVectorPtr);
313+
} catch (std::exception const &e) {
314+
delete DevicesVectorPtr;
315+
error_handler(e, __FILE__, __func__, __LINE__);
316+
return nullptr;
317+
}
318+
}

libsyclinterface/tests/test_sycl_device_selector_interface.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,7 @@ INSTANTIATE_TEST_SUITE_P(FilterSelectorCreation,
220220
"gpu:0",
221221
"gpu:1",
222222
"1",
223-
"0",
224-
"host"));
223+
"0"));
225224

226225
INSTANTIATE_TEST_SUITE_P(NegativeFilterSelectorCreation,
227226
TestUnsupportedFilters,

0 commit comments

Comments
 (0)