Skip to content

Commit 3497ccf

Browse files
committed
Use setdefault-oriented cache updates in core hot paths
Switch selected cache write sites to setdefault/get-based patterns and keep explicit comments where setdefault is intentionally not used for primitive value caches. Signed-off-by: Sebastian Berg <sebastianb@nvidia.com>
1 parent a9156b6 commit 3497ccf

6 files changed

Lines changed: 24 additions & 17 deletions

File tree

cuda_core/cuda/core/_device.pyx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,12 @@ cdef class DeviceProperties:
8585

8686
cdef inline int _get_cached_attribute(self, attr, default=0) except? -2:
8787
"""Retrieve the attribute value, using cache if applicable."""
88-
if attr not in self._cache:
89-
self._cache[attr] = self._get_attribute(attr, default)
90-
return self._cache[attr]
88+
cached = self._cache.get(attr)
89+
if cached is not None:
90+
return cached
91+
cdef int value = self._get_attribute(attr, default)
92+
self._cache[attr] = value # setdefault not needed for ints
93+
return value
9194

9295
@property
9396
def max_threads_per_block(self) -> int:
@@ -1131,11 +1134,11 @@ class Device:
11311134
def compute_capability(self) -> ComputeCapability:
11321135
"""Return a named tuple with 2 fields: major and minor."""
11331136
cdef DeviceProperties prop = self.properties
1134-
if "compute_capability" in prop._cache:
1135-
return prop._cache["compute_capability"]
1137+
cached = prop._cache.get("compute_capability")
1138+
if cached is not None:
1139+
return cached
11361140
cc = ComputeCapability(prop.compute_capability_major, prop.compute_capability_minor)
1137-
prop._cache["compute_capability"] = cc
1138-
return cc
1141+
return prop._cache.setdefault("compute_capability", cc)
11391142

11401143
@property
11411144
def arch(self) -> str:

cuda_core/cuda/core/_memory/_graph_memory_resource.pyi

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
from __future__ import annotations
44

5-
from functools import cache
6-
75
from cuda.core._device import Device
86
from cuda.core._memory._buffer import Buffer, MemoryResource
97
from cuda.core._stream import Stream
@@ -113,7 +111,6 @@ class GraphMemoryResource(cyGraphMemoryResource):
113111
...
114112

115113
@classmethod
116-
@cache
117114
def _create(cls, device_id: int) -> GraphMemoryResource:
118115
...
119116
__all__ = ['GraphMemoryResource']

cuda_core/cuda/core/_memory/_graph_memory_resource.pyx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ from cuda.core._resource_handles cimport (
1818
from cuda.core._stream cimport Stream_accept, Stream
1919
from cuda.core._utils.cuda_utils cimport HANDLE_RETURN
2020

21-
from functools import cache
2221
from typing import TYPE_CHECKING
2322

2423
if TYPE_CHECKING:
@@ -161,6 +160,8 @@ cdef class cyGraphMemoryResource(MemoryResource):
161160
return False
162161

163162

163+
cdef dict _mem_resource_cache = {}
164+
164165
class GraphMemoryResource(cyGraphMemoryResource):
165166
"""
166167
A memory resource for memory related to graphs.
@@ -185,9 +186,16 @@ class GraphMemoryResource(cyGraphMemoryResource):
185186
return cls._create(c_device_id)
186187

187188
@classmethod
188-
@cache
189189
def _create(cls, int device_id) -> GraphMemoryResource:
190-
return cyGraphMemoryResource.__new__(cls, device_id)
190+
# we use a dict currently, because functools.cache is currently less
191+
# thread-safe see also: https://github.com/python/cpython/issues/150708
192+
res = _mem_resource_cache.get(device_id)
193+
if res is not None:
194+
return res
195+
196+
# create new instance, but in case of a race may return another:
197+
new = cyGraphMemoryResource.__new__(cls, device_id)
198+
return _mem_resource_cache.setdefault(device_id, new)
191199

192200

193201
# Raise an exception if the given stream is capturing.

cuda_core/cuda/core/_memoryview.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ cdef inline bint _is_torch_tensor(object obj):
8080
cdef str mod = tp.__module__ or ""
8181
cdef bint result = mod.startswith("torch") and hasattr(obj, "data_ptr") \
8282
and _torch_version_check()
83-
_torch_type_cache[tp] = result
83+
_torch_type_cache[tp] = result # setdefault not needed for bools
8484
return result
8585

8686

cuda_core/cuda/core/_module.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ cdef class KernelAttributes:
8383
cdef int result
8484
with nogil:
8585
HANDLE_RETURN(cydriver.cuKernelGetAttribute(&result, attribute, as_cu(self._h_kernel), device_id))
86-
self._cache[cache_key] = result
86+
self._cache[cache_key] = result # setdefault not needed for ints
8787
return result
8888

8989
def __getitem__(self, device: Device | int) -> KernelAttributes:

cuda_core/cuda/core/graph/_graph_node.pyx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ _node_registry: weakref.WeakValueDictionary[int, GraphNode] = weakref.WeakValueD
7878

7979

8080
cdef inline GraphNode _registered(GraphNode n):
81-
_node_registry[<uintptr_t>n._h_node.get()] = n
82-
return n
81+
return _node_registry.setdefault(<uintptr_t>n._h_node.get(), n)
8382

8483

8584
cdef class GraphNode:

0 commit comments

Comments
 (0)