Skip to content

Commit 85ff9c2

Browse files
authored
Fix #1043: Fix memory leak in StridedMemoryView (#1048)
* Fix #1043: Fix memory leak in StridedMemoryView * Move location of test * Add relnote
1 parent 6f900d7 commit 85ff9c2

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

cuda_core/cuda/core/experimental/_memoryview.pyx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,23 @@ cdef class StridedMemoryView:
105105
else:
106106
pass
107107

108+
def __dealloc__(self):
109+
if self.dl_tensor == NULL:
110+
return
111+
112+
if cpython.PyCapsule_IsValid(
113+
self.metadata, DLPACK_VERSIONED_TENSOR_USED_NAME):
114+
data = cpython.PyCapsule_GetPointer(
115+
self.metadata, DLPACK_VERSIONED_TENSOR_USED_NAME)
116+
dlm_tensor_ver = <DLManagedTensorVersioned*>data
117+
dlm_tensor_ver.deleter(dlm_tensor_ver)
118+
elif cpython.PyCapsule_IsValid(
119+
self.metadata, DLPACK_TENSOR_USED_NAME):
120+
data = cpython.PyCapsule_GetPointer(
121+
self.metadata, DLPACK_TENSOR_USED_NAME)
122+
dlm_tensor = <DLManagedTensor*>data
123+
dlm_tensor.deleter(dlm_tensor)
124+
108125
@property
109126
def shape(self) -> tuple[int]:
110127
if self._shape is None and self.exporting_obj is not None:

cuda_core/docs/source/release/0.X.Y-notes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,4 @@ Fixes and enhancements
4848
- Make :class:`Buffer` creation more performant.
4949
- Enabled :class:`MemoryResource` subclasses to accept :class:`Device` objects, in addition to previously supported device ordinals.
5050
- Fixed a bug in :class:`Stream` and other classes where object cleanup would error during interpreter shutdown.
51+
- :class:`StridedMemoryView` of an underlying array using the DLPack protocol will no longer leak memory.

cuda_core/tests/test_memory.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: Apache-2.0
33

4+
import sys
5+
46
try:
57
from cuda.bindings import driver
68
except ImportError:
79
from cuda import cuda as driver
8-
10+
try:
11+
import numpy as np
12+
except ImportError:
13+
np = None
914
import ctypes
1015
import platform
1116

1217
import pytest
1318
from cuda.core.experimental import Buffer, Device, DeviceMemoryResource, MemoryResource
1419
from cuda.core.experimental._memory import DLDeviceType, IPCBufferDescriptor
1520
from cuda.core.experimental._utils.cuda_utils import handle_return
21+
from cuda.core.experimental.utils import StridedMemoryView
1622

1723
POOL_SIZE = 2097152 # 2MB size
1824

@@ -437,3 +443,14 @@ def test_mempool_attributes_ownership(mempool_device):
437443
with pytest.raises(RuntimeError, match="DeviceMemoryResource is expired"):
438444
_ = attributes.used_mem_high
439445
mr._mempool_handle = old_handle
446+
447+
448+
# Ensure that memory views dellocate their reference to dlpack tensors
449+
@pytest.mark.skipif(np is None, reason="numpy is not installed")
450+
def test_strided_memory_view_leak():
451+
arr = np.zeros(1048576, dtype=np.uint8)
452+
before = sys.getrefcount(arr)
453+
for idx in range(10):
454+
StridedMemoryView(arr, stream_ptr=-1)
455+
after = sys.getrefcount(arr)
456+
assert before == after

0 commit comments

Comments
 (0)