From 7fda3ea605ff367eeb64b73c2461fb91fc654aef Mon Sep 17 00:00:00 2001 From: Nader Al Awar Date: Mon, 13 Jan 2025 10:09:26 -0600 Subject: [PATCH 1/7] Change __cuda_stream__ from attribute to method --- cuda_core/cuda/core/experimental/_stream.py | 4 +--- cuda_core/docs/source/interoperability.rst | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/cuda_core/cuda/core/experimental/_stream.py b/cuda_core/cuda/core/experimental/_stream.py index 2baffb870d..38f23b413a 100644 --- a/cuda_core/cuda/core/experimental/_stream.py +++ b/cuda_core/cuda/core/experimental/_stream.py @@ -89,7 +89,7 @@ def _init(obj=None, *, options: Optional[StreamOptions] = None): if obj is not None: if not hasattr(obj, "__cuda_stream__"): raise ValueError - info = obj.__cuda_stream__ + info = obj.__cuda_stream__() assert info[0] == 0 self._mnff.handle = cuda.CUstream(info[1]) # TODO: check if obj is created under the current context/device @@ -132,7 +132,6 @@ def close(self): """ self._mnff.close() - @property def __cuda_stream__(self) -> Tuple[int, int]: """Return an instance of a __cuda_stream__ protocol.""" return (0, self.handle) @@ -279,7 +278,6 @@ def from_handle(handle: int) -> Stream: """ class _stream_holder: - @property def __cuda_stream__(self): return (0, handle) diff --git a/cuda_core/docs/source/interoperability.rst b/cuda_core/docs/source/interoperability.rst index 3bcdbe6807..a3736b2bc6 100644 --- a/cuda_core/docs/source/interoperability.rst +++ b/cuda_core/docs/source/interoperability.rst @@ -34,14 +34,13 @@ exposing their own stream types. To address this issue, we propose the ``__cuda_stream__`` protocol (currently version 0) as follows: For any Python objects that are meant to be interpreted as a stream, they -should add a ``__cuda_stream__`` attribute that returns a 2-tuple: The version number +should add a ``__cuda_stream__`` method that returns a 2-tuple: The version number (``0``) and the address of ``cudaStream_t`` (both as Python `int`): .. code-block:: python class MyStream: - @property def __cuda_stream__(self): return (0, self.ptr) From 30b21dac6900086e92651db65cdbe367faff0ac2 Mon Sep 17 00:00:00 2001 From: Nader Al Awar Date: Mon, 13 Jan 2025 10:34:16 -0600 Subject: [PATCH 2/7] Remove property decorator from StreamAdaptor in example --- cuda_core/examples/simple_multi_gpu_example.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cuda_core/examples/simple_multi_gpu_example.py b/cuda_core/examples/simple_multi_gpu_example.py index 89dd6cbea6..7b83d844c6 100644 --- a/cuda_core/examples/simple_multi_gpu_example.py +++ b/cuda_core/examples/simple_multi_gpu_example.py @@ -81,7 +81,6 @@ class StreamAdaptor: def __init__(self, obj): self.obj = obj - @property def __cuda_stream__(self): # Note: CuPy streams have a .ptr attribute return (0, self.obj.ptr) From 0d80142dc4ebe79102c21d3acc5db3e0a92afe57 Mon Sep 17 00:00:00 2001 From: Nader Al Awar Date: Mon, 13 Jan 2025 10:36:59 -0600 Subject: [PATCH 3/7] Add next release docs --- cuda_core/docs/source/release/0.2.0-notes.rst | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 cuda_core/docs/source/release/0.2.0-notes.rst diff --git a/cuda_core/docs/source/release/0.2.0-notes.rst b/cuda_core/docs/source/release/0.2.0-notes.rst new file mode 100644 index 0000000000..ae1e8a3c8a --- /dev/null +++ b/cuda_core/docs/source/release/0.2.0-notes.rst @@ -0,0 +1,7 @@ +``cuda.core`` v0.2.0 Release notes +================================== + +Highlights +---------- + +- Change ``__cuda_stream__`` from attribute to method \ No newline at end of file From 5376a4ea603f6b602d6b59815c00a1d3f1d51514 Mon Sep 17 00:00:00 2001 From: Nader Al Awar Date: Mon, 13 Jan 2025 11:49:36 -0600 Subject: [PATCH 4/7] Fix release docs --- cuda_core/docs/source/release.md | 1 + cuda_core/docs/source/release/0.2.0-notes.rst | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cuda_core/docs/source/release.md b/cuda_core/docs/source/release.md index a9e16d6e8a..b38d326093 100644 --- a/cuda_core/docs/source/release.md +++ b/cuda_core/docs/source/release.md @@ -5,6 +5,7 @@ maxdepth: 3 --- + 0.2.0 0.1.1 0.1.0 diff --git a/cuda_core/docs/source/release/0.2.0-notes.rst b/cuda_core/docs/source/release/0.2.0-notes.rst index ae1e8a3c8a..572567fd1d 100644 --- a/cuda_core/docs/source/release/0.2.0-notes.rst +++ b/cuda_core/docs/source/release/0.2.0-notes.rst @@ -1,7 +1,7 @@ ``cuda.core`` v0.2.0 Release notes ================================== -Highlights ----------- +Breaking changes +---------------- - Change ``__cuda_stream__`` from attribute to method \ No newline at end of file From 049a2f1049bfd1e6f716002aaad0321d1d808a7a Mon Sep 17 00:00:00 2001 From: Nader Al Awar Date: Tue, 14 Jan 2025 09:17:54 -0600 Subject: [PATCH 5/7] Check __cuda_stream__ attribute if method fails --- cuda_core/cuda/core/experimental/_stream.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cuda_core/cuda/core/experimental/_stream.py b/cuda_core/cuda/core/experimental/_stream.py index 38f23b413a..7ddc3ea090 100644 --- a/cuda_core/cuda/core/experimental/_stream.py +++ b/cuda_core/cuda/core/experimental/_stream.py @@ -89,7 +89,10 @@ def _init(obj=None, *, options: Optional[StreamOptions] = None): if obj is not None: if not hasattr(obj, "__cuda_stream__"): raise ValueError - info = obj.__cuda_stream__() + try: + info = obj.__cuda_stream__() + except TypeError: + info = obj.__cuda_stream__ assert info[0] == 0 self._mnff.handle = cuda.CUstream(info[1]) # TODO: check if obj is created under the current context/device From be3c43ee91d4aa45ae53a3b5a7e8d8d418c0916e Mon Sep 17 00:00:00 2001 From: Nader Al Awar Date: Tue, 14 Jan 2025 19:48:37 -0600 Subject: [PATCH 6/7] Add warning message if __cuda_stream__ attribute is used --- cuda_core/cuda/core/experimental/_stream.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cuda_core/cuda/core/experimental/_stream.py b/cuda_core/cuda/core/experimental/_stream.py index 7ddc3ea090..8f9590f4c4 100644 --- a/cuda_core/cuda/core/experimental/_stream.py +++ b/cuda_core/cuda/core/experimental/_stream.py @@ -5,6 +5,7 @@ from __future__ import annotations import os +import warnings import weakref from dataclasses import dataclass from typing import TYPE_CHECKING, Optional, Tuple, Union @@ -87,12 +88,16 @@ def _init(obj=None, *, options: Optional[StreamOptions] = None): if obj is not None and options is not None: raise ValueError("obj and options cannot be both specified") if obj is not None: - if not hasattr(obj, "__cuda_stream__"): - raise ValueError try: info = obj.__cuda_stream__() except TypeError: info = obj.__cuda_stream__ + warnings.simplefilter("once", DeprecationWarning) + warnings.warn( + "Implementing __cuda_stream__ as an attribute is deprecated; it must be implemented as a method", + category=DeprecationWarning, + ) + assert info[0] == 0 self._mnff.handle = cuda.CUstream(info[1]) # TODO: check if obj is created under the current context/device From 2db47435b574b464d0fe4260d256da67378e3796 Mon Sep 17 00:00:00 2001 From: Nader Al Awar Date: Wed, 15 Jan 2025 09:31:53 -0600 Subject: [PATCH 7/7] Replace __cuda_stream__ AttributeError with TypeError --- cuda_core/cuda/core/experimental/_stream.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cuda_core/cuda/core/experimental/_stream.py b/cuda_core/cuda/core/experimental/_stream.py index 8f9590f4c4..c50998db95 100644 --- a/cuda_core/cuda/core/experimental/_stream.py +++ b/cuda_core/cuda/core/experimental/_stream.py @@ -90,11 +90,14 @@ def _init(obj=None, *, options: Optional[StreamOptions] = None): if obj is not None: try: info = obj.__cuda_stream__() + except AttributeError as e: + raise TypeError(f"{type(obj)} object does not have a '__cuda_stream__' method") from e except TypeError: info = obj.__cuda_stream__ warnings.simplefilter("once", DeprecationWarning) warnings.warn( "Implementing __cuda_stream__ as an attribute is deprecated; it must be implemented as a method", + stacklevel=3, category=DeprecationWarning, )