Skip to content

Commit ea13ec6

Browse files
committed
address pickling review feedback
Raise UnpicklingError when the pickled device is not available, and name the queue in PicklingError for sub-device and non-default-context queues. Document that filter string ids depend on ONEAPI_DEVICE_SELECTOR.
1 parent 96ece36 commit ea13ec6

5 files changed

Lines changed: 44 additions & 8 deletions

File tree

‎dpctl/_sycl_device.pyx‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,10 +376,15 @@ def _rebuild_device(str filter_string, str name):
376376
"""Unpickles a :class:`dpctl.SyclDevice`.
377377
378378
Raises:
379-
pickle.UnpicklingError: if the device selected by ``filter_string``
380-
is not named ``name``.
379+
pickle.UnpicklingError: if no device matches ``filter_string``, or
380+
the device it selects is not named ``name``.
381381
"""
382-
dev = SyclDevice(filter_string)
382+
try:
383+
dev = SyclDevice(filter_string)
384+
except SyclDeviceCreationError as e:
385+
raise pickle.UnpicklingError(
386+
f"Device '{filter_string}' ('{name}') is not available"
387+
) from e
383388
if dev.name != name:
384389
raise pickle.UnpicklingError(
385390
f"Device '{filter_string}' is '{dev.name}', expected '{name}'"
@@ -1671,6 +1676,11 @@ cdef class SyclDevice(_SyclDevice):
16711676
def __reduce__(self):
16721677
"""Pickles a root device by its filter string and name.
16731678
1679+
The filter string's device id is relative to the devices visible
1680+
under ``ONEAPI_DEVICE_SELECTOR``. If the loading process sees a
1681+
different set of devices, the pickle may load onto another device
1682+
of the same name.
1683+
16741684
Raises:
16751685
pickle.PicklingError: if the device is not a root device.
16761686
"""

‎dpctl/_sycl_queue.pyx‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"""
2424

2525
from ._backend cimport ( # noqa: E211
26+
DPCTLContext_AreEq,
2627
DPCTLContext_Create,
2728
DPCTLContext_Delete,
2829
DPCTLDefaultSelector_Create,
@@ -103,6 +104,7 @@ from libc.stdlib cimport free, malloc
103104

104105
import collections.abc
105106
import logging
107+
import pickle
106108
import struct
107109
import sys
108110

@@ -2221,9 +2223,26 @@ cdef class SyclQueue(_SyclQueue):
22212223
"""Pickles the queue's context, device, and properties.
22222224
22232225
Raises:
2224-
pickle.PicklingError: if the queue's context is not the default
2225-
context of its device, or the device is not a root device.
2226+
pickle.PicklingError: if the queue's device is not a root device,
2227+
or its context is not the default context of that device.
22262228
"""
2229+
cdef DPCTLSyclContextRef CRef = NULL
2230+
cdef bint is_default_ctx = False
2231+
if self._device.parent_device is not None:
2232+
raise pickle.PicklingError(
2233+
f"Cannot pickle {self!r}: its device is not a root device"
2234+
)
2235+
CRef = DPCTLDeviceMgr_GetCachedContext(self._device.get_device_ref())
2236+
if CRef is not NULL:
2237+
is_default_ctx = DPCTLContext_AreEq(
2238+
CRef, self._context.get_context_ref()
2239+
)
2240+
DPCTLContext_Delete(CRef)
2241+
if not is_default_ctx:
2242+
raise pickle.PicklingError(
2243+
f"Cannot pickle {self!r}: its context is not the default "
2244+
"context of its device"
2245+
)
22272246
props = []
22282247
if DPCTLQueue_IsInOrder(self._queue_ref):
22292248
props.append("in_order")

‎dpctl/tests/test_sycl_device.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,13 @@ def test_device_unpickling_name_mismatch():
487487
_rebuild_device(dev.filter_string, dev.name + " (other)")
488488

489489

490+
def test_device_unpickling_missing_device():
491+
from dpctl._sycl_device import _rebuild_device
492+
493+
with pytest.raises(pickle.UnpicklingError, match="is not available"):
494+
_rebuild_device("opencl:gpu:999", "Missing device")
495+
496+
490497
def test_device_copy():
491498
sub_dev = get_sub_device_or_skip()
492499
root_dev = sub_dev.parent_device

‎dpctl/tests/test_sycl_queue.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,14 +452,14 @@ def test_queue_pickling_non_default_context():
452452
ctx = dpctl.SyclContext([dev])
453453
if ctx == q.sycl_context:
454454
pytest.skip("Context created from device list is the default context")
455-
with pytest.raises(pickle.PicklingError):
455+
with pytest.raises(pickle.PicklingError, match="SyclQueue.*context"):
456456
pickle.dumps(dpctl.SyclQueue(ctx, dev))
457457

458458

459459
def test_queue_pickling_sub_device():
460460
sub_dev = get_sub_device_or_skip()
461461
q = dpctl.SyclQueue(sub_dev)
462-
with pytest.raises(pickle.PicklingError):
462+
with pytest.raises(pickle.PicklingError, match="not a root device"):
463463
pickle.dumps(q)
464464

465465

‎dpctl/tests/test_sycl_usm.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ def test_pickling_non_default_context(memory_ctor):
229229
if ctx == dpctl.SyclContext(dev):
230230
pytest.skip("Context created from device list is the default context")
231231
mobj = memory_ctor(64, queue=dpctl.SyclQueue(ctx, dev))
232-
with pytest.raises(pickle.PicklingError):
232+
with pytest.raises(pickle.PicklingError, match="SyclQueue"):
233233
pickle.dumps(mobj)
234234

235235

0 commit comments

Comments
 (0)