From 71b3bda2462197741fb8b86286736271a49cb268 Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Wed, 17 Dec 2025 12:26:59 -0500 Subject: [PATCH 1/5] test: add failing test case for zero-sized array input to `StridedMemoryView.from_cuda_array_interface` --- cuda_core/tests/test_utils.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cuda_core/tests/test_utils.py b/cuda_core/tests/test_utils.py index 1bb432de6c..c778a9e493 100644 --- a/cuda_core/tests/test_utils.py +++ b/cuda_core/tests/test_utils.py @@ -413,3 +413,23 @@ def test_view_sliced_external_negative_offset(stride_order, view_as): assert sliced_view._layout.itemsize == a_sliced.itemsize == layout.itemsize assert sliced_view.shape == a_sliced.shape assert sliced_view._layout.strides_in_bytes == a_sliced.strides + + +@pytest.mark.parametrize( + "api", + [ + StridedMemoryView.from_dlpack, + StridedMemoryView.from_cuda_array_interface, + ], +) +@pytest.mark.parametrize("shape", [(0,), (0, 0), (0, 0, 0)]) +@pytest.mark.parametrize("dtype", [np.int64, np.uint8, np.float64]) +def test_view_zero_size_array(api, shape, dtype): + cp = pytest.importorskip("cupy") + + x = cp.empty(shape, dtype=dtype) + smv = api(x, stream_ptr=0) + + assert smv.size == 0 + assert smv.shape == shape + assert smv.dtype == np.dtype(dtype) From 23666b3ef72d377b4d68fb1dac1e8319f8d75d3f Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Wed, 17 Dec 2025 12:27:49 -0500 Subject: [PATCH 2/5] fix: only pluck out device id if the data buffer pointer coming from CAI is valid --- cuda_core/cuda/core/_memoryview.pyx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cuda_core/cuda/core/_memoryview.pyx b/cuda_core/cuda/core/_memoryview.pyx index 24cf3ad99f..972e79424f 100644 --- a/cuda_core/cuda/core/_memoryview.pyx +++ b/cuda_core/cuda/core/_memoryview.pyx @@ -582,10 +582,13 @@ cpdef StridedMemoryView view_as_cai(obj, stream_ptr, view=None): buf.dl_tensor = NULL buf.ptr, buf.readonly = cai_data["data"] buf.is_device_accessible = True - buf.device_id = handle_return( - driver.cuPointerGetAttribute( - driver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL, - buf.ptr)) + if buf.ptr != 0: + buf.device_id = handle_return( + driver.cuPointerGetAttribute( + driver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL, + buf.ptr)) + else: + buf.device_id = -1 cdef intptr_t producer_s, consumer_s stream_ptr = int(stream_ptr) From 8198373f21f71a5122c39fab93621d4eb88b1529 Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Wed, 17 Dec 2025 12:57:39 -0500 Subject: [PATCH 3/5] chore: set zero-sized array device to the current device --- cuda_core/cuda/core/_memoryview.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_core/cuda/core/_memoryview.pyx b/cuda_core/cuda/core/_memoryview.pyx index 972e79424f..c12cbbaa8a 100644 --- a/cuda_core/cuda/core/_memoryview.pyx +++ b/cuda_core/cuda/core/_memoryview.pyx @@ -588,7 +588,7 @@ cpdef StridedMemoryView view_as_cai(obj, stream_ptr, view=None): driver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL, buf.ptr)) else: - buf.device_id = -1 + buf.device_id = handle_return(driver.cuCtxGetDevice()) cdef intptr_t producer_s, consumer_s stream_ptr = int(stream_ptr) From 0dc144d57e35a687bf6aefc24f9c141f251d0a7f Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Wed, 17 Dec 2025 14:11:38 -0500 Subject: [PATCH 4/5] docs: add note about changes --- cuda_core/docs/source/release/0.5.0-notes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/cuda_core/docs/source/release/0.5.0-notes.rst b/cuda_core/docs/source/release/0.5.0-notes.rst index 8164ceb4c1..ca981bcd89 100644 --- a/cuda_core/docs/source/release/0.5.0-notes.rst +++ b/cuda_core/docs/source/release/0.5.0-notes.rst @@ -61,6 +61,7 @@ None. Fixes and enhancements ---------------------- +- Zero-size arrays are now supported as inputs to ``StridedMemoryView.from_cuda_array_interface``. - Most CUDA resources can be hashed now. - Python ``bool`` objects are now converted to C++ ``bool`` type when passed as kernel arguments (previously converted to ``int``). - Restored v0.3.x :class:`MemoryResource` behaviors and missing MR attributes for backward compatibility. From 5a33e7a306015e9eaef0516ea10a66a4903cdcd6 Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Wed, 17 Dec 2025 15:02:42 -0500 Subject: [PATCH 5/5] docs: clarify --- cuda_core/docs/source/release/0.5.0-notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_core/docs/source/release/0.5.0-notes.rst b/cuda_core/docs/source/release/0.5.0-notes.rst index ca981bcd89..f41ed70cb1 100644 --- a/cuda_core/docs/source/release/0.5.0-notes.rst +++ b/cuda_core/docs/source/release/0.5.0-notes.rst @@ -61,7 +61,7 @@ None. Fixes and enhancements ---------------------- -- Zero-size arrays are now supported as inputs to ``StridedMemoryView.from_cuda_array_interface``. +- Zero-size arrays are now supported as inputs when constructing ``StridedMemoryView``. - Most CUDA resources can be hashed now. - Python ``bool`` objects are now converted to C++ ``bool`` type when passed as kernel arguments (previously converted to ``int``). - Restored v0.3.x :class:`MemoryResource` behaviors and missing MR attributes for backward compatibility.