• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IntelPython / dpctl / 13402228542

18 Feb 2025 11:40PM UTC coverage: 88.169% (-0.06%) from 88.224%
13402228542

Pull #1992

github

web-flow
Merge f60d32ac2 into df4f4b16c
Pull Request #1992: Add `get_devices` method to `dpctl.SyclPlatform` class

3163 of 3658 branches covered (86.47%)

Branch coverage included in aggregate %.

52 of 71 new or added lines in 2 files covered. (73.24%)

1 existing line in 1 file now uncovered.

11980 of 13517 relevant lines covered (88.63%)

7149.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.78
/dpctl/_sycl_platform.pyx
1
#                      Data Parallel Control (dpctl)
1✔
2
#
3
# Copyright 2020-2025 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
# distutils: language = c++
18
# cython: language_level=3
19
# cython: linetrace=True
20

21
""" Implements SyclPlatform Cython extension type.
22
"""
23

24
from libcpp cimport bool
25

26
from ._backend cimport (  # noqa: E211
27
    DPCTLCString_Delete,
28
    DPCTLDeviceSelector_Delete,
29
    DPCTLDeviceVector_Delete,
30
    DPCTLDeviceVector_GetAt,
31
    DPCTLDeviceVector_Size,
32
    DPCTLDeviceVectorRef,
33
    DPCTLFilterSelector_Create,
34
    DPCTLPlatform_AreEq,
35
    DPCTLPlatform_Copy,
36
    DPCTLPlatform_Create,
37
    DPCTLPlatform_CreateFromSelector,
38
    DPCTLPlatform_Delete,
39
    DPCTLPlatform_GetBackend,
40
    DPCTLPlatform_GetDefaultContext,
41
    DPCTLPlatform_GetDevices,
42
    DPCTLPlatform_GetName,
43
    DPCTLPlatform_GetPlatforms,
44
    DPCTLPlatform_GetVendor,
45
    DPCTLPlatform_GetVersion,
46
    DPCTLPlatform_Hash,
47
    DPCTLPlatformMgr_GetInfo,
48
    DPCTLPlatformMgr_PrintInfo,
49
    DPCTLPlatformVector_Delete,
50
    DPCTLPlatformVector_GetAt,
51
    DPCTLPlatformVector_Size,
52
    DPCTLPlatformVectorRef,
53
    DPCTLSyclContextRef,
54
    DPCTLSyclDeviceRef,
55
    DPCTLSyclDeviceSelectorRef,
56
    DPCTLSyclPlatformRef,
57
    _backend_type,
58
    _device_type,
59
)
60

61
import warnings
1✔
62

63
from ._sycl_context import SyclContextCreationError
1✔
64
from .enum_types import backend_type
1✔
65
from .enum_types import device_type as device_type_t
1✔
66

67
from ._sycl_context cimport SyclContext
68
from ._sycl_device cimport SyclDevice
69

70
__all__ = [
1✔
71
    "get_platforms",
72
    "lsplatform",
73
    "SyclPlatform",
74
]
75

76
cdef class _SyclPlatform:
77
    """ Data owner for SyclPlatform
78
    """
79

80
    def __dealloc__(self):
81
        DPCTLPlatform_Delete(self._platform_ref)
1✔
82
        DPCTLCString_Delete(self._name)
1✔
83
        DPCTLCString_Delete(self._vendor)
1✔
84
        DPCTLCString_Delete(self._version)
1✔
85

86

87
cdef void _init_helper(_SyclPlatform platform, DPCTLSyclPlatformRef PRef):
1✔
88
    "Populate attributes of class from opaque reference PRef"
89
    platform._platform_ref = PRef
1✔
90
    platform._name = DPCTLPlatform_GetName(PRef)
1✔
91
    platform._version = DPCTLPlatform_GetVersion(PRef)
1✔
92
    platform._vendor = DPCTLPlatform_GetVendor(PRef)
1✔
93

94

95
cdef class SyclPlatform(_SyclPlatform):
96
    """ SyclPlatform(self, arg=None)
97
    Python class representing ``sycl::platform`` class.
98

99
    There are two ways of creating a :class:`.SyclPlatform`
100
    instance:
101

102
    - Invoking the constructor with no arguments creates a
103
      platform using the default selector.
104

105
    :Example:
106
        .. code-block:: python
107

108
            import dpctl
109

110
            # Create a SyclPlatform for default-selected device
111
            pl = dpctl.SyclPlatform()
112
            print(pl.name, pl.version)
113

114
    - Invoking the constructor with specific filter selector string that
115
      creates a queue for the device corresponding to the filter string.
116

117
    :Example:
118
        .. code-block:: python
119

120
            import dpctl
121

122
            # Create a SyclPlatform for device selected by
123
            # filter-selector string
124
            pl = dpctl.SyclPlatform("opencl:cpu")
125
            print(pl.name, pl.version)
126
    """
127

128
    @staticmethod
129
    cdef SyclPlatform _create(DPCTLSyclPlatformRef pref):
1✔
130
        """
131
        This function calls ``DPCTLPlatform_Delete(pref)``.
132

133
        The user of this function must pass a copy to keep the
134
        pref argument alive.
135
        """
136
        cdef _SyclPlatform p = _SyclPlatform.__new__(_SyclPlatform)
1✔
137
        # Initialize the attributes of the SyclPlatform object
138
        _init_helper(<_SyclPlatform>p, pref)
1✔
139
        return SyclPlatform(p)
1✔
140

141
    cdef int _init_from__SyclPlatform(self, _SyclPlatform other):
1✔
142
        self._platform_ref = DPCTLPlatform_Copy(other._platform_ref)
1✔
143
        if (self._platform_ref is NULL):
1✔
144
            return -1
×
145
        self._name = DPCTLPlatform_GetName(self._platform_ref)
1✔
146
        self._version = DPCTLPlatform_GetVersion(self._platform_ref)
1✔
147
        self._vendor = DPCTLPlatform_GetVendor(self._platform_ref)
1✔
148

149
    cdef int _init_from_cstring(self, const char *string):
1✔
150
        cdef DPCTLSyclDeviceSelectorRef DSRef = NULL
1✔
151
        DSRef = DPCTLFilterSelector_Create(string)
1✔
152
        ret = self._init_from_selector(DSRef)
1✔
153
        return ret
1✔
154

155
    cdef int _init_from_selector(self, DPCTLSyclDeviceSelectorRef DSRef):
1✔
156
        # Initialize the SyclPlatform from a DPCTLSyclDeviceSelectorRef
157
        cdef DPCTLSyclPlatformRef PRef = DPCTLPlatform_CreateFromSelector(DSRef)
1✔
158
        DPCTLDeviceSelector_Delete(DSRef)
1✔
159
        if PRef is NULL:
1✔
160
            return -1
1✔
161
        else:
162
            _init_helper(self, PRef)
1✔
163
            return 0
1✔
164

165
    cdef DPCTLSyclPlatformRef get_platform_ref(self):
1✔
166
        """ Returns the ``DPCTLSyclPlatformRef`` pointer for this class.
167
        """
168
        return self._platform_ref
1✔
169

170
    @property
171
    def __name__(self):
172
        return "SyclPlatform"
1✔
173

174
    def __repr__(self):
175
        return (
1✔
176
            "<dpctl."
177
            + self.__name__
1✔
178
            + " ["
1✔
179
            + self.name
1✔
180
            + ", "
1✔
181
            + self.vendor
1✔
182
            + ", "
1✔
183
            + " "
1✔
184
            + self.version + "] at {}>".format(hex(id(self)))
1✔
185
        )
186

187
    def __cinit__(self, arg=None):
188
        if type(arg) is unicode:
1✔
189
            string = bytes(<unicode>arg, "utf-8")
1✔
190
            filter_c_str = string
1✔
191
            ret = self._init_from_cstring(filter_c_str)
1✔
192
            if ret == -1:
1✔
193
                raise ValueError(
1✔
194
                    "Could not create a SyclPlatform with the selector string"
195
                )
196
        elif isinstance(arg, unicode):
1✔
197
            string = bytes(<unicode>unicode(arg), "utf-8")
×
198
            filter_c_str = string
×
199
            ret = self._init_from_cstring(filter_c_str)
×
200
            if ret == -1:
×
201
                raise ValueError(
×
202
                    "Could not create a SyclPlatform with the selector string"
203
                )
204
        elif isinstance(arg, _SyclPlatform):
1✔
205
            ret = self._init_from__SyclPlatform(arg)
1✔
206
            if ret == -1:
1✔
207
                raise ValueError(
×
208
                    "Could not create SyclPlatform from _SyclPlatform instance"
209
                )
210
        elif arg is None:
1✔
211
            PRef = DPCTLPlatform_Create()
1✔
212
            if PRef is NULL:
1✔
213
                raise ValueError(
×
214
                    "Could not create a SyclPlatform from default selector"
215
                )
216
            else:
217
                _init_helper(self, PRef)
1✔
218
        else:
219
            raise ValueError(
×
220
                "Invalid argument. Argument should be a str object specifying "
221
                "a SYCL filter selector string."
222
            )
223

224
    def print_platform_info(self, verbosity=0):
1✔
225
        """ Print information about the SYCL platform.
226

227
        The level of information printed out by the function can be controlled
228
        by the optional ``vebosity`` setting.
229

230
        - **Verbosity level 0**: Prints out the list of platforms and their
231
          names.
232
        - **Verbosity level 1**: Prints out the name, version, vendor,
233
          backend, number of devices for each platform.
234
        - **Verbosity level 2**: At the highest level of verbosity
235
          everything in the previous levels along with the name, version,
236
          and filter string for each device is printed.
237

238
        Args:
239
            verbosity (Literal[0, 1, 2], optional):.
240
                The verbosity controls how much information is printed by the
241
                function. Value ``0`` is the lowest level set by default and ``2``
242
                is the highest level to print the most verbose output.
243
                Default: ``0``
244
        """
245
        cdef size_t v = 0
1✔
246

247
        if not isinstance(verbosity, int):
1✔
248
            warnings.warn(
×
249
                "Illegal verbosity level. Accepted values are 0, 1, or 2. "
250
                "Using the default verbosity level of 0."
251
            )
252
        else:
253
            v = <size_t>(verbosity)
1✔
254
            if v > 2:
1✔
255
                warnings.warn(
×
256
                    "Illegal verbosity level. Accepted values are 0, 1, or 2. "
257
                    "Using the default verbosity level of 0."
258
                )
259
                v = 0
×
260
        DPCTLPlatformMgr_PrintInfo(self._platform_ref, v)
1✔
261

262
    @property
263
    def vendor(self):
264
        """
265
        Returns the platform vendor name as a string.
266

267
        Returns:
268
            str:
269
                Vendor name
270
        """
271
        return self._vendor.decode()
1✔
272

273
    @property
274
    def version(self):
275
        """ Returns a backend-defined driver version as a string.
276

277
        Returns:
278
            str:
279
                Version of the backend-defined driver
280
        """
281
        return self._version.decode()
1✔
282

283
    @property
284
    def name(self):
285
        """ Returns the name of the platform as a string.
286

287
        Returns:
288
            str:
289
                Name of the platform
290
        """
291
        return self._name.decode()
1✔
292

293
    @property
294
    def backend(self):
295
        """Returns the backend_type enum value for this platform
296

297
        Returns:
298
            backend_type:
299
                The backend for the platform.
300
        """
301
        cdef _backend_type BTy = (
302
            DPCTLPlatform_GetBackend(self._platform_ref)
1✔
303
        )
304
        if BTy == _backend_type._CUDA:
1✔
305
            return backend_type.cuda
×
306
        elif BTy == _backend_type._HIP:
307
            return backend_type.hip
×
308
        elif BTy == _backend_type._LEVEL_ZERO:
309
            return backend_type.level_zero
×
310
        elif BTy == _backend_type._OPENCL:
311
            return backend_type.opencl
1✔
312
        else:
313
            raise ValueError("Unknown backend type.")
×
314

315
    @property
316
    def default_context(self):
317
        """Returns the default platform context for this platform
318

319
        Returns:
320
            :class:`dpctl.SyclContext`
321
                The default context for the platform.
322
        Raises:
323
            SyclContextCreationError
324
                If default_context is not supported
325
        """
326
        cdef DPCTLSyclContextRef CRef = (
327
            DPCTLPlatform_GetDefaultContext(self._platform_ref)
1✔
328
        )
329

330
        if (CRef == NULL):
1✔
331
            raise SyclContextCreationError(
×
332
                "Getting default_context ran into a problem"
333
            )
334
        else:
335
            return SyclContext._create(CRef)
1✔
336

337
    cdef bool equals(self, SyclPlatform other):
1✔
338
        """
339
        Returns true if the :class:`dpctl.SyclPlatform` argument has the
340
        same underlying ``DPCTLSyclPlatformRef`` object as this
341
        :class:`dpctl.SyclPlatform` instance.
342

343
        Returns:
344
            bool:
345
                ``True`` if the two :class:`dpctl.SyclPlatform` objects
346
                point to the same ``DPCTLSyclPlatformRef`` object, otherwise
347
                ``False``.
348
        """
349
        return DPCTLPlatform_AreEq(self._platform_ref, other.get_platform_ref())
1✔
350

351
    def __eq__(self, other):
352
        """
353
        Returns True if the :class:`dpctl.SyclPlatform` argument has the
354
        same underlying ``DPCTLSyclPlatformRef`` object as this
355
        :class:`dpctl.SyclPlatform` instance.
356

357
        Returns:
358
            bool:
359
                ``True`` if the two :class:`dpctl.SyclPlatform` objects
360
                point to the same ``DPCTLSyclPlatformRef`` object, otherwise
361
                ``False``.
362
        """
363
        if isinstance(other, SyclPlatform):
1✔
364
            return self.equals(<SyclPlatform> other)
1✔
365
        else:
366
            return False
×
367

368
    def __hash__(self):
369
        """
370
        Returns a hash value by hashing the underlying ``sycl::platform`` object.
371

372
        Returns:
373
            int:
374
                Hash value
375
        """
376
        return DPCTLPlatform_Hash(self._platform_ref)
1✔
377

378
    def get_devices(self, device_type=device_type_t.all):
1✔
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 (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".
389
                Default: ``dpctl.device_type.all``.
390

391
        Returns:
392
            list:
393
                A :obj:`list` of :class:`dpctl.SyclDevice` objects
394
                that belong to this platform.
395

396
        Raises:
397
            TypeError:
398
                If `device_type` is not a str or :class:`dpctl.device_type`
399
                enum.
400
            ValueError:
401
                If the ``DPCTLPlatform_GetDevices`` call returned
402
                ``NULL`` instead of a ``DPCTLDeviceVectorRef`` object.
403
        """
404
        cdef _device_type DTy = _device_type._ALL_DEVICES
1✔
405
        cdef DPCTLDeviceVectorRef DVRef = NULL
1✔
406
        cdef size_t num_devs
407
        cdef size_t i
408
        cdef DPCTLSyclDeviceRef DRef
409

410
        if isinstance(device_type, str):
1✔
411
            dty_str = device_type.strip().lower()
1✔
412
            if dty_str == "accelerator":
1✔
413
                DTy = _device_type._ACCELERATOR
1✔
414
            elif dty_str == "all":
1✔
415
                DTy = _device_type._ALL_DEVICES
1✔
416
            elif dty_str == "cpu":
1✔
417
                DTy = _device_type._CPU
1✔
418
            elif dty_str == "gpu":
1✔
419
                DTy = _device_type._GPU
1✔
420
            else:
NEW
421
                DTy = _device_type._UNKNOWN_DEVICE
×
422
        elif isinstance(device_type, device_type_t):
1✔
423
            if device_type == device_type_t.all:
1✔
424
                DTy = _device_type._ALL_DEVICES
1✔
425
            elif device_type == device_type_t.accelerator:
1✔
426
                DTy = _device_type._ACCELERATOR
1✔
427
            elif device_type == device_type_t.cpu:
1✔
428
                DTy = _device_type._CPU
1✔
429
            elif device_type == device_type_t.gpu:
1✔
430
                DTy = _device_type._GPU
1✔
431
            else:
NEW
432
                DTy = _device_type._UNKNOWN_DEVICE
×
433
        else:
NEW
434
            raise TypeError(
×
435
                "device type should be specified as a str or an "
436
                "``enum_types.device_type``."
437
            )
438
        DVRef = DPCTLPlatform_GetDevices(self.get_platform_ref(), DTy)
1✔
439
        if (DVRef is NULL):
1✔
NEW
440
            raise ValueError("Internal error: NULL device vector encountered")
×
441
        num_devs = DPCTLDeviceVector_Size(DVRef)
1✔
442
        devices = []
1✔
443
        for i in range(num_devs):
1✔
444
            DRef = DPCTLDeviceVector_GetAt(DVRef, i)
1✔
445
            devices.append(SyclDevice._create(DRef))
1✔
446
        DPCTLDeviceVector_Delete(DVRef)
1✔
447

448
        return devices
1✔
449

450

451
def lsplatform(verbosity=0):
1✔
452
    """
453
    Prints out the list of available SYCL platforms, and optionally extra
454
    metadata about each platform.
455

456
    The level of information printed out by the function can be controlled by
457
    the optional ``vebosity`` setting.
458

459
    - **Verbosity level 0**: Prints out the list of platforms and their names.
460
    - **Verbosity level 1**: Prints out the name, version, vendor, backend,
461
      number of devices for each platform.
462
    - **Verbosity level 2**: At the highest level of verbosity everything in the
463
      previous levels along with the name, version, and filter string for each
464
      device is printed.
465

466
    At verbosity level 2 (highest level) the following output is generated.
467

468
    :Example:
469
        On a system with an OpenCL CPU driver, OpenCL GPU driver,
470
        Level Zero GPU driver, running the command:
471

472
        .. code-block:: bash
473

474
            $ python -c "import dpctl; dpctl.lsplatform(verbosity=2)"
475

476
        outputs
477

478
        .. code-block:: text
479
            :caption: Sample output of lsplatform(verbosity=2)
480

481
            Platform 0::
482
                Name        Intel(R) OpenCL
483
                Version     OpenCL 2.1 LINUX
484
                Vendor      Intel(R) Corporation
485
                Profile     FULL_PROFILE
486
                Backend     opencl
487
                Devices     1
488
                    Device 0::
489
                    Name            Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
490
                    Driver version  2020.11.11.0.13_160000
491
                    Device type     cpu
492
            Platform 1::
493
                Name        Intel(R) OpenCL HD Graphics
494
                Version     OpenCL 3.0
495
                Vendor      Intel(R) Corporation
496
                Profile     FULL_PROFILE
497
                Backend     opencl
498
                Devices     1
499
                    Device 0::
500
                    Name            Intel(R) Graphics Gen9 [0x3e98]
501
                    Driver version  20.47.18513
502
                    Device type     gpu
503
            Platform 2::
504
                Name        Intel(R) Level-Zero
505
                Version     1.0
506
                Vendor      Intel(R) Corporation
507
                Profile     FULL_PROFILE
508
                Backend     level_zero
509
                Devices     1
510
                    Device 0::
511
                    Name            Intel(R) Graphics Gen9 [0x3e98]
512
                    Driver version  1.0.18513
513
                    Device type     gpu
514

515
    Args:
516
        verbosity (Literal[0,1,2], optional):
517
            The verbosity controls how much information is printed by the
518
            function. 0 is the lowest level set by default and 2 is the highest
519
            level to print the most verbose output. Default: `0`.
520
    """
521
    cdef DPCTLPlatformVectorRef PVRef = NULL
1✔
522
    cdef size_t v = 0
1✔
523
    cdef size_t size = 0
1✔
524
    cdef const char * info_str = NULL
1✔
525
    cdef DPCTLSyclPlatformRef PRef = NULL
1✔
526

527
    if not isinstance(verbosity, int):
1✔
UNCOV
528
        warnings.warn(
×
529
            "Illegal verbosity level. Accepted values are 0, 1, or 2. "
530
            "Using the default verbosity level of 0."
531
        )
532
    else:
533
        v = <size_t>(verbosity)
1✔
534
        if v > 2:
1✔
535
            warnings.warn(
1✔
536
                "Illegal verbosity level. Accepted values are 0, 1, or 2. "
537
                "Using the default verbosity level of 0."
538
            )
539
            v = 0
1✔
540

541
    PVRef = DPCTLPlatform_GetPlatforms()
1✔
542

543
    if PVRef is not NULL:
1✔
544
        size = DPCTLPlatformVector_Size(PVRef)
1✔
545
        for i in range(size):
1✔
546
            if v != 0:
1✔
547
                print("Platform ", i, "::")
1✔
548
            PRef = DPCTLPlatformVector_GetAt(PVRef, i)
1✔
549
            info_str = DPCTLPlatformMgr_GetInfo(PRef,v)
1✔
550
            py_info = <bytes> info_str
1✔
551
            DPCTLCString_Delete(info_str)
1✔
552
            DPCTLPlatform_Delete(PRef)
1✔
553
            print(py_info.decode("utf-8"),end='')
1✔
554
    DPCTLPlatformVector_Delete(PVRef)
1✔
555

556

557
cpdef list get_platforms():
1✔
558
    """
559
    Returns a list of all available SYCL platforms on the system.
560

561
    Returns:
562
        List[:class:`.SyclPlatform`]:
563
            A list of SYCL platforms on the system.
564
    """
565
    cdef list platforms = []
1✔
566
    cdef DPCTLPlatformVectorRef PVRef = NULL
1✔
567
    cdef size_t size = 0
1✔
568

569
    PVRef = DPCTLPlatform_GetPlatforms()
1✔
570
    if PVRef is not NULL:
1✔
571
        size = DPCTLPlatformVector_Size(PVRef)
1✔
572
        for i in range(size):
1✔
573
            PRef = DPCTLPlatformVector_GetAt(PVRef, i)
1✔
574
            P = SyclPlatform._create(PRef)
1✔
575
            platforms.append(P)
1✔
576

577
    DPCTLPlatformVector_Delete(PVRef)
1✔
578
    return platforms
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc