From b5538c54b1bff56519f3883fcb29e2fe11c4e8e0 Mon Sep 17 00:00:00 2001 From: Nikita Grigorian Date: Wed, 4 Nov 2026 11:41:03 -0800 Subject: [PATCH] skip tests on devices without the needed USM aspect Move the USM aspect check from the memset and fill tests into dpctl/tests/helper and use it wherever tests allocate shared, host, or device USM. --- dpctl/tests/helper/__init__.py | 2 ++ dpctl/tests/helper/_helper.py | 23 ++++++++++++ dpctl/tests/test_sycl_context.py | 4 ++- dpctl/tests/test_sycl_ipc_memory.py | 6 ++++ dpctl/tests/test_sycl_queue_copy.py | 19 +++++++--- dpctl/tests/test_sycl_queue_fill.py | 26 +++++++------- dpctl/tests/test_sycl_queue_memcpy.py | 3 ++ dpctl/tests/test_sycl_queue_memset.py | 18 +++------- dpctl/tests/test_sycl_usm.py | 51 ++++++++++++++------------- 9 files changed, 96 insertions(+), 56 deletions(-) diff --git a/dpctl/tests/helper/__init__.py b/dpctl/tests/helper/__init__.py index be5f8d2e33..016ac37f92 100644 --- a/dpctl/tests/helper/__init__.py +++ b/dpctl/tests/helper/__init__.py @@ -22,6 +22,7 @@ has_cpu, has_gpu, has_sycl_platforms, + skip_if_usm_unsupported, ) __all__ = [ @@ -30,4 +31,5 @@ "has_gpu", "has_sycl_platforms", "get_queue_or_skip", + "skip_if_usm_unsupported", ] diff --git a/dpctl/tests/helper/_helper.py b/dpctl/tests/helper/_helper.py index 5857b23195..e90491be60 100644 --- a/dpctl/tests/helper/_helper.py +++ b/dpctl/tests/helper/_helper.py @@ -49,3 +49,26 @@ def get_queue_or_skip(args=()): except dpctl.SyclQueueCreationError: pytest.skip(f"Queue could not be created from {args}") return q + + +def skip_if_usm_unsupported(mem_cls, syclobj=None): + """Skips the test if the device of ``syclobj`` (a device or a queue, + the default device if ``None``) cannot allocate ``mem_cls`` memory. + """ + import dpctl.memory as dpm + + if syclobj is None: + try: + syclobj = dpctl.SyclDevice() + except dpctl.SyclDeviceCreationError: + pytest.skip("No SYCL devices available") + dev = ( + syclobj.sycl_device if isinstance(syclobj, dpctl.SyclQueue) else syclobj + ) + supported = { + dpm.MemoryUSMShared: dev.has_aspect_usm_shared_allocations, + dpm.MemoryUSMHost: dev.has_aspect_usm_host_allocations, + dpm.MemoryUSMDevice: dev.has_aspect_usm_device_allocations, + } + if not supported[mem_cls]: + pytest.skip(f"{mem_cls.__name__} is not supported on {dev.name}") diff --git a/dpctl/tests/test_sycl_context.py b/dpctl/tests/test_sycl_context.py index 058bb7ad7f..d87e94505f 100644 --- a/dpctl/tests/test_sycl_context.py +++ b/dpctl/tests/test_sycl_context.py @@ -20,7 +20,7 @@ import dpctl -from .helper import create_invalid_capsule +from .helper import create_invalid_capsule, skip_if_usm_unsupported list_of_valid_filter_selectors = [ "opencl", @@ -170,7 +170,9 @@ def test_context_multi_device(): q2 = dpctl.SyclQueue(ctx, d2) import dpctl.memory as dpm + skip_if_usm_unsupported(dpm.MemoryUSMShared, q1) shmem_1 = dpm.MemoryUSMShared(256, queue=q1) + skip_if_usm_unsupported(dpm.MemoryUSMDevice, q2) shmem_2 = dpm.MemoryUSMDevice(256, queue=q2) shmem_2.copy_from_device(shmem_1) # create context for single sub-device diff --git a/dpctl/tests/test_sycl_ipc_memory.py b/dpctl/tests/test_sycl_ipc_memory.py index 3a300d0925..773022ac4f 100644 --- a/dpctl/tests/test_sycl_ipc_memory.py +++ b/dpctl/tests/test_sycl_ipc_memory.py @@ -32,6 +32,8 @@ SyclIPCOpenMemHandle, ) +from .helper import skip_if_usm_unsupported + pytestmark = pytest.mark.skipif( not IPCMemoryHandle.is_available(), reason="IPC memory not supported in this build", @@ -68,12 +70,14 @@ def test_get_handle_from_device_memory(self): def test_get_handle_rejects_shared_memory(self): q = _get_ipc_queue() + skip_if_usm_unsupported(MemoryUSMShared, q) mem = MemoryUSMShared(1024, queue=q) with pytest.raises(TypeError): SyclIPCGetMemHandle(mem) def test_get_handle_rejects_host_memory(self): q = _get_ipc_queue() + skip_if_usm_unsupported(MemoryUSMHost, q) mem = MemoryUSMHost(1024, queue=q) with pytest.raises(TypeError): SyclIPCGetMemHandle(mem) @@ -136,11 +140,13 @@ def test_normal_memory_is_not_ipc(self): def test_shared_memory_is_not_ipc(self): q = _get_ipc_queue() + skip_if_usm_unsupported(MemoryUSMShared, q) mem = MemoryUSMShared(1024, queue=q) assert not isinstance(mem, MemoryIPCDevice) def test_host_memory_is_not_ipc(self): q = _get_ipc_queue() + skip_if_usm_unsupported(MemoryUSMHost, q) mem = MemoryUSMHost(1024, queue=q) assert not isinstance(mem, MemoryIPCDevice) diff --git a/dpctl/tests/test_sycl_queue_copy.py b/dpctl/tests/test_sycl_queue_copy.py index c584ba26b9..0491fcb3d6 100644 --- a/dpctl/tests/test_sycl_queue_copy.py +++ b/dpctl/tests/test_sycl_queue_copy.py @@ -22,9 +22,12 @@ import dpctl import dpctl.memory +from .helper import skip_if_usm_unsupported + def _create_memory(q): nbytes = 1024 + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mobj = dpctl.memory.MemoryUSMShared(nbytes, queue=q) return mobj @@ -97,9 +100,9 @@ def test_copy_type_error(): @pytest.mark.parametrize( "usm_type", [ - lambda n, q: dpctl.memory.MemoryUSMShared(n, queue=q), - lambda n, q: dpctl.memory.MemoryUSMHost(n, queue=q), - lambda n, q: dpctl.memory.MemoryUSMDevice(n, queue=q), + dpctl.memory.MemoryUSMShared, + dpctl.memory.MemoryUSMHost, + dpctl.memory.MemoryUSMDevice, ], ids=["shared", "host", "device"], ) @@ -113,8 +116,9 @@ def test_copy_with_dtype_valid(dtype, element_size, usm_type): num_elements = 16 nbytes = num_elements * element_size - src = usm_type(nbytes, q) - dst = usm_type(nbytes, q) + skip_if_usm_unsupported(usm_type, q) + src = usm_type(nbytes, queue=q) + dst = usm_type(nbytes, queue=q) # For device memory, use host buffer for init and verification if isinstance(src, dpctl.memory.MemoryUSMDevice): @@ -155,6 +159,7 @@ def test_copy_async_with_dtype_valid(): num_elements = 10 nbytes = num_elements * element_size + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) src = dpctl.memory.MemoryUSMShared(nbytes, queue=q) dst = dpctl.memory.MemoryUSMShared(nbytes, queue=q) @@ -191,6 +196,7 @@ def test_copy_count_is_in_elements(dtype, element_size): num_elements = 4 nbytes = num_elements * element_size + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) src = dpctl.memory.MemoryUSMShared(nbytes, queue=q) dst = dpctl.memory.MemoryUSMShared(nbytes, queue=q) @@ -220,6 +226,7 @@ def test_copy_with_invalid_dtype(): pytest.skip("Default constructor for SyclQueue failed") nbytes = 64 + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) src = dpctl.memory.MemoryUSMShared(nbytes, queue=q) dst = dpctl.memory.MemoryUSMShared(nbytes, queue=q) @@ -265,6 +272,7 @@ def test_copy_with_dtype_mixed_sources(): # Host to USM src_host = np.arange(num_elements, dtype=np.int64) + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) dst_usm = dpctl.memory.MemoryUSMShared(nbytes, queue=q) q.copy(dst_usm, src_host, num_elements, dtype=dtype) @@ -284,6 +292,7 @@ def test_copy_without_dtype_backward_compat(): pytest.skip("Default constructor for SyclQueue failed") nbytes = 32 + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) src = dpctl.memory.MemoryUSMShared(nbytes, queue=q) dst = dpctl.memory.MemoryUSMShared(nbytes, queue=q) diff --git a/dpctl/tests/test_sycl_queue_fill.py b/dpctl/tests/test_sycl_queue_fill.py index 76546858c0..3c890f5935 100644 --- a/dpctl/tests/test_sycl_queue_fill.py +++ b/dpctl/tests/test_sycl_queue_fill.py @@ -22,6 +22,8 @@ import dpctl import dpctl.memory +from .helper import skip_if_usm_unsupported + # Maps a dtype string to the NumPy dtype used to build the expected result. _dtype_to_np = { "i1": np.int8, @@ -63,17 +65,6 @@ ] -def _skip_if_usm_unsupported(q, mem_cls): - dev = q.sycl_device - supported = { - dpctl.memory.MemoryUSMShared: dev.has_aspect_usm_shared_allocations, - dpctl.memory.MemoryUSMHost: dev.has_aspect_usm_host_allocations, - dpctl.memory.MemoryUSMDevice: dev.has_aspect_usm_device_allocations, - } - if not supported[mem_cls]: - pytest.skip(f"{mem_cls.__name__} is not supported on this device") - - def _read_back(mem, nbytes): """Return the first ``nbytes`` bytes of a USM allocation as ``bytes``.""" if isinstance(mem, dpctl.memory.MemoryUSMDevice): @@ -92,7 +83,7 @@ def test_fill_with_dtype_valid(dtype, mem_cls): q = dpctl.SyclQueue() except dpctl.SyclQueueCreationError: pytest.skip("Default constructor for SyclQueue failed") - _skip_if_usm_unsupported(q, mem_cls) + skip_if_usm_unsupported(mem_cls, q) np_dt = _dtype_to_np[dtype] value = _fill_values[dtype] @@ -114,6 +105,7 @@ def test_fill_default_dtype_is_bytewise(): pytest.skip("Default constructor for SyclQueue failed") nbytes = 64 + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(nbytes, queue=q) q.fill(mem, 0, nbytes) @@ -130,6 +122,7 @@ def test_fill_signed_negative_value(): pytest.skip("Default constructor for SyclQueue failed") num_elements = 8 + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(num_elements, queue=q) q.fill(mem, -1, num_elements, dtype="i1") @@ -143,6 +136,7 @@ def test_fill_async(): pytest.skip("Default constructor for SyclQueue failed") num_elements = 32 + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(num_elements, queue=q) e = q.fill_async(mem, 0xAB, num_elements) @@ -162,6 +156,7 @@ def test_fill_async_with_dtype(): num_elements = 10 nbytes = num_elements * 8 + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(nbytes, queue=q) e = q.fill_async(mem, value, num_elements, dtype="f8") e.wait() @@ -178,6 +173,7 @@ def test_fill_async_with_dep_events(): num_elements = 64 half = num_elements // 2 + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(num_elements, queue=q) e1 = q.fill_async(mem, 0x11, num_elements) @@ -194,6 +190,7 @@ def test_fill_async_bad_dep_events(): except dpctl.SyclQueueCreationError: pytest.skip("Default constructor for SyclQueue failed") + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(16, queue=q) with pytest.raises(TypeError): @@ -211,6 +208,7 @@ def test_fill_complex_from_real_scalar(dtype): num_elements = 8 nbytes = num_elements * np.dtype(np_dt).itemsize + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(nbytes, queue=q) q.fill(mem, 2.0, num_elements, dtype=dtype) @@ -236,6 +234,7 @@ def test_fill_count_is_in_elements(dtype, element_size): num_elements = 8 nbytes = num_elements * element_size + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(nbytes, queue=q) # Seed the whole allocation with a known sentinel to verify the untouched @@ -261,6 +260,7 @@ def test_fill_with_invalid_dtype(): except dpctl.SyclQueueCreationError: pytest.skip("Default constructor for SyclQueue failed") + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(64, queue=q) for bad_dtype in ["i3", "f16", "u16", "x4", "42", "float", ""]: @@ -291,6 +291,7 @@ def test_fill_value_out_of_range(dtype, value): except dpctl.SyclQueueCreationError: pytest.skip("Default constructor for SyclQueue failed") + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(64, queue=q) with pytest.raises(ValueError): @@ -321,6 +322,7 @@ def test_fill_count_out_of_bounds(): pytest.skip("Default constructor for SyclQueue failed") nbytes = 64 + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mem = dpctl.memory.MemoryUSMShared(nbytes, queue=q) q.fill(mem, 0, nbytes, dtype="u1") diff --git a/dpctl/tests/test_sycl_queue_memcpy.py b/dpctl/tests/test_sycl_queue_memcpy.py index 7d13f7ee48..1efeee2a9d 100644 --- a/dpctl/tests/test_sycl_queue_memcpy.py +++ b/dpctl/tests/test_sycl_queue_memcpy.py @@ -22,9 +22,12 @@ import dpctl import dpctl.memory +from .helper import skip_if_usm_unsupported + def _create_memory(q): nbytes = 1024 + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) mobj = dpctl.memory.MemoryUSMShared(nbytes, queue=q) return mobj diff --git a/dpctl/tests/test_sycl_queue_memset.py b/dpctl/tests/test_sycl_queue_memset.py index fefdbe2537..7d681b3027 100644 --- a/dpctl/tests/test_sycl_queue_memset.py +++ b/dpctl/tests/test_sycl_queue_memset.py @@ -22,8 +22,11 @@ import dpctl import dpctl.memory +from .helper import skip_if_usm_unsupported + def _create_memory(q, nbytes=1024): + skip_if_usm_unsupported(dpctl.memory.MemoryUSMShared, q) return dpctl.memory.MemoryUSMShared(nbytes, queue=q) @@ -41,24 +44,13 @@ def _read_back(q, mobj, nbytes): return bytes(host) -def _skip_if_usm_unsupported(q, mem_cls): - dev = q.sycl_device - supported = { - dpctl.memory.MemoryUSMShared: dev.has_aspect_usm_shared_allocations, - dpctl.memory.MemoryUSMHost: dev.has_aspect_usm_host_allocations, - dpctl.memory.MemoryUSMDevice: dev.has_aspect_usm_device_allocations, - } - if not supported[mem_cls]: - pytest.skip(f"{mem_cls.__name__} is not supported on this device") - - @pytest.mark.parametrize("mem_cls", _MEMORY_CLASSES) def test_memset_fills_whole_allocation(mem_cls): try: q = dpctl.SyclQueue() except dpctl.SyclQueueCreationError: pytest.skip("Default constructor for SyclQueue failed") - _skip_if_usm_unsupported(q, mem_cls) + skip_if_usm_unsupported(mem_cls, q) nbytes = 256 mobj = mem_cls(nbytes, queue=q) @@ -140,7 +132,7 @@ def test_memset_async(mem_cls): q = dpctl.SyclQueue() except dpctl.SyclQueueCreationError: pytest.skip("Default constructor for SyclQueue failed") - _skip_if_usm_unsupported(q, mem_cls) + skip_if_usm_unsupported(mem_cls, q) nbytes = 64 mobj = mem_cls(nbytes, queue=q) diff --git a/dpctl/tests/test_sycl_usm.py b/dpctl/tests/test_sycl_usm.py index 398a07b216..bb5302d002 100644 --- a/dpctl/tests/test_sycl_usm.py +++ b/dpctl/tests/test_sycl_usm.py @@ -27,6 +27,8 @@ as_usm_memory, ) +from .helper import skip_if_usm_unsupported + class Dummy(MemoryUSMShared): """ @@ -49,6 +51,7 @@ def test_memory_create(memory_ctor): queue = dpctl.SyclQueue() except dpctl.SyclQueueCreationError: pytest.skip("SyclQueue() failed, skip further testing...") + skip_if_usm_unsupported(memory_ctor, queue) mobj = memory_ctor(nbytes, alignment=64, queue=queue) assert mobj.nbytes == nbytes assert hasattr(mobj, "__sycl_usm_array_interface__") @@ -65,9 +68,10 @@ def test_memory_create(memory_ctor): def test_memory_create_with_np(): nbytes = 16384 try: - dpctl.SyclQueue() + q = dpctl.SyclQueue() except dpctl.SyclQueueCreationError: pytest.skip("SyclQueue() failed, skip further testing...") + skip_if_usm_unsupported(MemoryUSMShared, q) mobj = dpctl.memory.MemoryUSMShared(np.int64(nbytes)) assert mobj.nbytes == nbytes assert hasattr(mobj, "__sycl_usm_array_interface__") @@ -79,6 +83,7 @@ def _create_memory(): queue = dpctl.SyclQueue() except dpctl.SyclQueueCreationError: pytest.skip("SyclQueue() failed, skip further testing...") + skip_if_usm_unsupported(MemoryUSMShared, queue) mobj = MemoryUSMShared(nbytes, alignment=64, queue=queue) return mobj @@ -160,10 +165,8 @@ def test_zero_copy(): def test_pickling(memory_ctor): import pickle - try: - mobj = memory_ctor(1024, alignment=64) - except dpctl.SyclDeviceCreationError: - pytest.skip("No SYCL devices available") + skip_if_usm_unsupported(memory_ctor) + mobj = memory_ctor(1024, alignment=64) host_src_obj = _create_host_buf(mobj.nbytes) mobj.copy_from_host(host_src_obj) @@ -182,10 +185,8 @@ def test_pickling(memory_ctor): def test_pickling_reconstructor_invalid_type(memory_ctor): import pickle - try: - mobj = memory_ctor(1024, alignment=64) - except dpctl.SyclDeviceCreationError: - pytest.skip("No SYCL devices available") + skip_if_usm_unsupported(memory_ctor) + mobj = memory_ctor(1024, alignment=64) good_pickle_bytes = pickle.dumps(mobj) usm_types = expected_usm_type_str(memory_ctor).encode("utf-8") i = good_pickle_bytes.rfind(usm_types) @@ -222,6 +223,7 @@ def test_create_with_size_and_alignment_and_queue(memory_ctor): q = dpctl.SyclQueue() except dpctl.SyclQueueCreationError: pytest.skip("SyclQueue() failed, skip further testing") + skip_if_usm_unsupported(memory_ctor, q) m = memory_ctor(1024, alignment=64, queue=q) assert m.nbytes == 1024 assert m.get_usm_type() == expected_usm_type_str(memory_ctor) @@ -233,6 +235,7 @@ def test_create_with_size_and_queue(memory_ctor): q = dpctl.SyclQueue() except dpctl.SyclQueueCreationError: pytest.skip("SyclQueue() failed, skip further testing") + skip_if_usm_unsupported(memory_ctor, q) m = memory_ctor(1024, queue=q) assert m.nbytes == 1024 assert m.get_usm_type() == expected_usm_type_str(memory_ctor) @@ -240,10 +243,8 @@ def test_create_with_size_and_queue(memory_ctor): def test_create_with_size_and_alignment(memory_ctor): - try: - m = memory_ctor(1024, alignment=64) - except dpctl.SyclDeviceCreationError: - pytest.skip("No SYCL devices available") + skip_if_usm_unsupported(memory_ctor) + m = memory_ctor(1024, alignment=64) assert m.nbytes == 1024 assert m.get_usm_type() == expected_usm_type_str(memory_ctor) assert m.get_usm_type_enum() == expected_usm_type_enum(memory_ctor) @@ -251,10 +252,8 @@ def test_create_with_size_and_alignment(memory_ctor): def test_usm_type_exceptions(): ctor = MemoryUSMDevice - try: - m = ctor(1024) - except dpctl.SyclDeviceCreationError: - pytest.skip("No SYCL devices available") + skip_if_usm_unsupported(ctor) + m = ctor(1024) assert m.nbytes == 1024 q = m.sycl_queue assert m.get_usm_type(syclobj=q) == expected_usm_type_str(ctor) @@ -269,10 +268,9 @@ def test_usm_type_exceptions(): def test_sycl_usm_array_interface(memory_ctor): - try: - m = memory_ctor(256) - except dpctl.SyclDeviceCreationError: - pytest.skip("No SYCL devices available") + skip_if_usm_unsupported(memory_ctor) + skip_if_usm_unsupported(MemoryUSMShared) + m = memory_ctor(256) m2 = Dummy(m.nbytes) hb = np.random.randint(0, 256, size=256, dtype="|u1") m2.copy_from_host(hb) @@ -537,10 +535,8 @@ def test_cpython_api(memory_ctor): import ctypes import sys - try: - mobj = memory_ctor(1024) - except dpctl.SyclDeviceCreationError: - pytest.skip("No SYCL devices available") + skip_if_usm_unsupported(memory_ctor) + mobj = memory_ctor(1024) mod = sys.modules[mobj.__class__.__module__] # get capsules storing function pointers mem_ptr_fn_cap = mod.__pyx_capi__["Memory_GetUsmPointer"] @@ -617,6 +613,8 @@ def test_memory_construction_from_other_memory_objects(): q = dpctl.SyclQueue() except dpctl.SyclQueueCreationError: pytest.skip("Default queue could not be created") + for mem_cls in (MemoryUSMShared, MemoryUSMDevice, MemoryUSMHost): + skip_if_usm_unsupported(mem_cls, q) m_sh = MemoryUSMShared(256, queue=q) m_de = MemoryUSMDevice(256, queue=q) m_ho = MemoryUSMHost(256, queue=q) @@ -638,6 +636,7 @@ def test_memory_copy_between_contexts(): q = dpctl.SyclQueue("cpu") except dpctl.SyclQueueCreationError: pytest.skip("CPU queue could not be created") + skip_if_usm_unsupported(MemoryUSMDevice, q) d = q.sycl_device n = d.max_compute_units n_half = n // 2 @@ -660,6 +659,8 @@ def test_memset(): except dpctl.SyclQueueCreationError: pytest.skip("Default queue could not be created") + for mem_cls in (MemoryUSMShared, MemoryUSMDevice, MemoryUSMHost): + skip_if_usm_unsupported(mem_cls, q) n = 4086 m_de = MemoryUSMDevice(n, queue=q) m_sh = MemoryUSMShared(n, queue=q)