Skip to content

Commit 9ba9199

Browse files
authored
cuda.core: accept dict for XyzOptions that are extension types (#2634)
* cuda.core: accept dict for options in MemoryResource constructors * excempt some APIs cython annotation typing
1 parent e68adde commit 9ba9199

7 files changed

Lines changed: 68 additions & 0 deletions

File tree

cuda_core/cuda/core/_context.pyx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ from collections.abc import Sequence
88
from dataclasses import dataclass
99
from typing import TYPE_CHECKING
1010

11+
import cython
12+
1113
from cuda.bindings cimport cydriver
1214
from cuda.core._device_resources cimport DeviceResources, SMResource, WorkqueueResource
1315
from cuda.core._device_resources import SMResource, WorkqueueResource
@@ -99,6 +101,7 @@ cdef class Context:
99101
Context_check_open(self)
100102
return DeviceResources._init_from_ctx(self._h_context, self._device_id)
101103

104+
@cython.annotation_typing(False)
102105
def create_stream(self, options: StreamOptions | None = None) -> Stream:
103106
"""Create a new stream bound to this green context.
104107

cuda_core/cuda/core/_memory/_device_memory_resource.pyx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ from cuda.core._utils.cuda_utils cimport (
2020
check_or_create_options,
2121
HANDLE_RETURN,
2222
)
23+
24+
import cython
2325
from dataclasses import dataclass
2426
import multiprocessing
2527
import platform # no-cython-lint
@@ -146,6 +148,7 @@ cdef class DeviceMemoryResource(_MemPool):
146148
def __cinit__(self, *args, **kwargs) -> None:
147149
self._dev_id = cydriver.CU_DEVICE_INVALID
148150

151+
@cython.annotation_typing(False)
149152
def __init__(
150153
self,
151154
device_id: Device | int,

cuda_core/cuda/core/_memory/_managed_memory_resource.pyx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ from cuda.core._utils.cuda_utils cimport HANDLE_RETURN
1313
from cuda.core._utils.cuda_utils cimport check_or_create_options # no-cython-lint
1414
from cuda.core._utils.cuda_utils import CUDAError # no-cython-lint
1515

16+
import cython
1617
from dataclasses import dataclass
1718
import threading
1819
from typing import TYPE_CHECKING
@@ -97,6 +98,7 @@ cdef class ManagedMemoryResource(_MemPool):
9798
memory pools.
9899
"""
99100

101+
@cython.annotation_typing(False)
100102
def __init__(self, options: ManagedMemoryResourceOptions | None = None) -> None:
101103
_MMR_init(self, options)
102104

cuda_core/cuda/core/_memory/_pinned_memory_resource.pyx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ from cuda.core._utils.cuda_utils cimport (
2121
HANDLE_RETURN,
2222
)
2323

24+
import cython
2425
from dataclasses import dataclass
2526
import multiprocessing
2627
import platform # no-cython-lint
@@ -109,6 +110,7 @@ cdef class PinnedMemoryResource(_MemPool):
109110
See :class:`DeviceMemoryResource` for more details on IPC usage patterns.
110111
"""
111112

113+
@cython.annotation_typing(False)
112114
def __init__(self, options: PinnedMemoryResourceOptions | None = None) -> None:
113115
_PMR_init(self, options)
114116

cuda_core/cuda/core/_stream.pyx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ cdef class Stream:
123123
return Stream._from_handle(cls, get_per_thread_stream())
124124

125125
@classmethod
126+
@cython.annotation_typing(False)
126127
def _init(cls, obj: IsStreamType | None = None, options: StreamOptions | None = None,
127128
device_id: int | None = None, ctx: Context | None = None) -> Stream:
128129
cdef StreamHandle h_stream
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
"""Backward-compatibility checks for undocumented dict options in MR constructors."""
5+
6+
import pytest
7+
from helpers.constants import POOL_SIZE
8+
from helpers.memory import (
9+
create_managed_memory_resource_or_skip,
10+
create_pinned_memory_resource_or_xfail,
11+
skip_if_managed_memory_unsupported,
12+
skip_if_pinned_memory_unsupported,
13+
)
14+
15+
from cuda.core import Device, DeviceMemoryResource
16+
17+
18+
@pytest.mark.agent_authored(model="gpt-5.3-codex")
19+
def test_device_mr_accepts_dict_keyword(init_cuda):
20+
device = Device()
21+
if not device.properties.memory_pools_supported:
22+
pytest.skip("Device does not support memory pool operations")
23+
device.set_current()
24+
mr = DeviceMemoryResource(device, options={"max_size": POOL_SIZE})
25+
buf = mr.allocate(64, stream=device.default_stream)
26+
buf.close(stream=device.default_stream)
27+
mr.close()
28+
29+
30+
@pytest.mark.agent_authored(model="gpt-5.3-codex")
31+
def test_pinned_mr_accepts_dict_keyword(init_cuda):
32+
device = Device()
33+
skip_if_pinned_memory_unsupported(device)
34+
device.set_current()
35+
mr = create_pinned_memory_resource_or_xfail(options={"max_size": POOL_SIZE}, xfail_device=device)
36+
buf = mr.allocate(64, stream=device.default_stream)
37+
buf.close(stream=device.default_stream)
38+
mr.close()
39+
40+
41+
@pytest.mark.agent_authored(model="gpt-5.3-codex")
42+
def test_managed_mr_accepts_dict_keyword(init_cuda):
43+
device = Device()
44+
skip_if_managed_memory_unsupported(device)
45+
device.set_current()
46+
mr = create_managed_memory_resource_or_skip(options={})
47+
buf = mr.allocate(64, stream=device.default_stream)
48+
buf.close(stream=device.default_stream)
49+
mr.close()

cuda_core/tests/test_stream.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ def test_stream_init_with_options(init_cuda):
2828
assert stream.priority == 0
2929

3030

31+
@pytest.mark.agent_authored(model="glm-5.2")
32+
def test_stream_init_with_dict_options(init_cuda):
33+
"""Device.create_stream accepts a plain dict for options (backward compat)."""
34+
stream = Device().create_stream(options={"nonblocking": True, "priority": 0})
35+
assert stream.is_nonblocking is True
36+
assert stream.priority == 0
37+
38+
3139
def test_stream_handle(init_cuda):
3240
stream = Device().create_stream(options=StreamOptions())
3341
assert isinstance(stream.handle, driver.CUstream)

0 commit comments

Comments
 (0)