Coverage for cuda/core/_memory/_device_memory_resource.pyx: 65.79%
76 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-16 01:23 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-16 01:23 +0000
1# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2#
3# SPDX-License-Identifier: Apache-2.0
5from __future__ import annotations
7from cuda.bindings cimport cydriver
8from cuda.core._memory._location cimport cumemlocation_from_id
9from cuda.core._memory._memory_pool cimport (
10 _MemPool, MP_check_open, MP_init_create_pool, MP_raise_release_threshold,
11)
12from cuda.core._memory cimport _ipc
13from cuda.core._memory._ipc cimport IPCAllocationHandle
14from cuda.core._rt cimport as_cu, get_device_mempool, get_last_error
15from cuda.core._utils.cuda_utils cimport (
16 check_or_create_options,
17 HANDLE_RETURN,
18)
20from dataclasses import dataclass
21import multiprocessing
22import platform # no-cython-lint
23import uuid
25from cuda.core._memory._peer_access_utils import PeerAccessibleBySetProxy, replace_peer_accessible_by
26from cuda.core._utils.cuda_utils import check_multiprocessing_start_method
28from typing import TYPE_CHECKING
30if TYPE_CHECKING:
31 from cuda.core._device import Device
33__all__ = ['DeviceMemoryResource', 'DeviceMemoryResourceOptions']
36@dataclass
37cdef class DeviceMemoryResourceOptions:
38 """Customizable :obj:`~_memory.DeviceMemoryResource` options.
40 Attributes
41 ----------
42 ipc_enabled : bool, optional
43 Specifies whether to create an IPC-enabled memory pool. When set to
44 True, the memory pool and its allocations can be shared with other
45 processes. (Default to False)
47 max_size : int, optional
48 Maximum pool size. When set to 0, defaults to a system-dependent value.
49 (Default to 0)
50 """
51 ipc_enabled : bool = False
52 max_size : int = 0
55cdef class DeviceMemoryResource(_MemPool):
56 """
57 A device memory resource managing a stream-ordered memory pool.
59 Parameters
60 ----------
61 device_id : Device | int
62 Device or Device ordinal for which a memory resource is constructed.
64 options : DeviceMemoryResourceOptions
65 Memory resource creation options.
67 If set to `None`, the memory resource uses the driver's current
68 stream-ordered memory pool for the specified `device_id`. If no memory
69 pool is set as current, the driver's default memory pool for the device
70 is used.
72 If not set to `None`, a new memory pool is created, which is owned by
73 the memory resource.
75 When using an existing (current or default) memory pool, the returned
76 device memory resource does not own the pool (`is_handle_owned` is
77 `False`), and closing the resource has no effect.
79 Notes
80 -----
81 To create an IPC-Enabled memory resource (MR) that is capable of sharing
82 allocations between processes, specify ``ipc_enabled=True`` in the initializer
83 option. Sharing an allocation is a two-step procedure that involves
84 mapping a memory resource and then mapping buffers owned by that resource.
85 These steps can be accomplished in several ways.
87 An IPC-enabled memory resource can allocate memory buffers but cannot
88 receive shared buffers. Mapping an MR to another process creates a "mapped
89 memory resource" (MMR). An MMR cannot allocate memory buffers and can only
90 receive shared buffers. MRs and MMRs are both of type
91 :class:`DeviceMemoryResource` and can be distinguished via
92 :attr:`DeviceMemoryResource.is_mapped`.
94 An MR is shared via an allocation handle accessed through the
95 :attr:`DeviceMemoryResource.allocation_handle` property. The allocation
96 handle has a platform-specific interpretation; however, memory IPC is
97 currently only supported for Linux, and in that case allocation handles
98 are file descriptors. After sending an allocation handle to another
99 process, it can be used to create an MMR by invoking
100 :meth:`DeviceMemoryResource.from_allocation_handle`.
102 Buffers can be shared as serializable descriptors accessed through the
103 :attr:`Buffer.ipc_descriptor` property. In a receiving process, a shared
104 buffer is created by invoking :meth:`Buffer.from_ipc_descriptor` with an
105 MMR and buffer descriptor, where the MMR corresponds to the MR that
106 created the described buffer.
108 To help manage the association between memory resources and buffers, a
109 registry is provided. Every MR has a unique identifier (UUID). MMRs can be
110 registered by calling :meth:`DeviceMemoryResource.register` with the UUID
111 of the corresponding MR. Registered MMRs can be looked up via
112 :meth:`DeviceMemoryResource.from_registry`. When registering MMRs in this
113 way, the use of buffer descriptors can be avoided. Instead, buffer objects
114 can themselves be serialized and transferred directly. Serialization embeds
115 the UUID, which is used to locate the correct MMR during reconstruction.
117 IPC-enabled memory resources interoperate with the :mod:`multiprocessing`
118 module to provide a simplified interface. This approach can avoid direct
119 use of allocation handles, buffer descriptors, MMRs, and the registry. When
120 using :mod:`multiprocessing` to spawn processes or send objects through
121 communication channels such as :class:`multiprocessing.Queue`,
122 :class:`multiprocessing.Pipe`, or :class:`multiprocessing.Connection`,
123 :class:`Buffer` objects may be sent directly, and in such cases the process
124 for creating MMRs and mapping buffers will be handled automatically.
126 For greater efficiency when transferring many buffers, one may also send
127 MRs and buffers separately. When an MR is sent via :mod:`multiprocessing`,
128 an MMR is created and registered in the receiving process. Subsequently,
129 buffers may be serialized and transferred using ordinary :mod:`pickle`
130 methods. The reconstruction procedure uses the registry to find the
131 associated MMR. Unpickling a :class:`Buffer` performs an IPC import from
132 the embedded descriptor; only unpickle buffers received from trusted peers.
134 Warning
135 -------
136 IPC descriptors and pickled buffers cross a trust boundary between
137 cooperating same-host processes. A malicious peer can supply crafted
138 descriptor fields. Use :meth:`Buffer.from_ipc_descriptor` only with
139 descriptors from trusted peers, and do not unpickle buffers from
140 untrusted sources.
141 """
143 def __cinit__(self, *args, **kwargs) -> None:
144 self._dev_id = cydriver.CU_DEVICE_INVALID 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjc[ kclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLc{ | } ~ a abw bbcbe dbebr fbf gbd E hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbMci j k l b c FbGbHbIbJbNcOcPcQcRcScTcUcVcx y z F s KbG q p t LbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4bWc5bXcYcZc0cm v n o 1c2c3c4c5c6c6b7b7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
146 def __init__(
147 self,
148 device_id: Device | int,
149 options: DeviceMemoryResourceOptions | None = None
150 ) -> None:
151 _DMR_init(self, device_id, options) 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjc[ kclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLc{ | } ~ a abw bbcbe dbebr fbf gbd E hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbMci j k l b c FbGbHbIbJbNcOcPcQcRcScTcUcVcx y z F s KbG q p t LbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4bWc5bXcYcZc0cm v n o 1c2c3c4c5c6c6b7b7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
153 def __reduce__(self) -> tuple[object, ...]:
154 MP_check_open(self) 1awbc
155 return DeviceMemoryResource.from_registry, (self.uuid,) 1awbc
157 @staticmethod
158 def from_registry(uuid: uuid.UUID) -> DeviceMemoryResource: # no-cython-lint
159 """
160 Obtain a registered mapped memory resource.
162 Raises
163 ------
164 RuntimeError
165 If no mapped memory resource is found in the registry.
166 """
167 return <DeviceMemoryResource>(_ipc.MP_from_registry(uuid)) 1dE
169 def register(self, uuid: uuid.UUID) -> DeviceMemoryResource: # no-cython-lint
170 """
171 Register a mapped memory resource.
173 Returns
174 -------
175 The registered mapped memory resource. If one was previously registered
176 with the given key, it is returned.
177 """
178 return <DeviceMemoryResource>(_ipc.MP_register(self, uuid)) 2tdd E
180 @classmethod
181 def from_allocation_handle(
182 cls, device_id: Device | int, alloc_handle: int | IPCAllocationHandle
183 ) -> DeviceMemoryResource:
184 """Create a device memory resource from an allocation handle.
186 Construct a new `DeviceMemoryResource` instance that imports a memory
187 pool from a shareable handle. The memory pool is marked as owned, and
188 the resource is associated with the specified `device_id`.
190 Parameters
191 ----------
192 device_id : int | Device
193 The ID of the device or a Device object for which the memory
194 resource is created.
196 alloc_handle : int | IPCAllocationHandle
197 The shareable handle of the device memory resource to import. If an
198 integer is supplied, it must represent a valid platform-specific
199 handle. It is the caller's responsibility to close that handle.
201 Returns
202 -------
203 A new device memory resource instance with the imported handle.
204 """
205 cdef DeviceMemoryResource mr = <DeviceMemoryResource>( 1fd
206 _ipc.MP_from_allocation_handle(cls, alloc_handle)) 2tdf d
207 from .._device import Device 1fd
208 mr._dev_id = Device(device_id).device_id 1fd
209 return mr 1fd
211 @property
212 def allocation_handle(self) -> IPCAllocationHandle:
213 """Shareable handle for this memory pool (requires IPC).
215 The handle can be used to share the memory pool with other processes.
216 The handle is cached in this `MemoryResource` and owned by it.
217 """
218 MP_check_open(self) 2ada bdcde r tdf d ddedfdudvdgdhdwdidjdxdkdldmdydndodpdg h qdrdsdi j k l b c x u m v n o
219 if not self.is_ipc_enabled: 2ada bdcde r tdf d ddedfdudvdgdhdwdidjdxdkdldmdydndodpdg h qdrdsdi j k l b c u m v n o
220 raise RuntimeError("Memory resource is not IPC-enabled") 1u
221 return self._ipc_data._alloc_handle 2ada bdcde r tdf d ddedfdudvdgdhdwdidjdxdkdldmdydndodpdg h qdrdsdi j k l b c m v n o
223 @property
224 def device_id(self) -> int:
225 """The associated device ordinal."""
226 return self._dev_id 2- . / : ; = ? @ zdAd] ^ Bd_ Cd` DdEdFdGdada bdcde f ddedfdgdhdidjdkdldmdndodpdg h qdrdsdi j k l b c FbGby z s Lbm n o A B C 8b9bH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , D
228 @property
229 def peer_accessible_by(self) -> PeerAccessibleBySetProxy:
230 """
231 Get or set the devices that can access allocations from this memory
232 pool. Access can be modified at any time and affects all allocations
233 from this memory pool.
235 Returns a set-like proxy of :obj:`~_device.Device` objects that manages
236 peer access. Inputs are accepted as either :obj:`~_device.Device`
237 objects or device-ordinal :class:`int` values.
239 Examples
240 --------
241 >>> dmr = DeviceMemoryResource(0)
242 >>> dmr.peer_accessible_by = {1} # grant access to device 1
243 >>> assert 1 in dmr.peer_accessible_by
244 >>> dmr.peer_accessible_by.add(2) # update access to include device 2
245 >>> dmr.peer_accessible_by = [] # revoke peer access
246 """
247 MP_check_open(self) 1xFt
248 return PeerAccessibleBySetProxy(self) 1xFt
250 @peer_accessible_by.setter
251 def peer_accessible_by(self, devices) -> None:
252 replace_peer_accessible_by(self, devices) 1t
254 @property
255 def is_device_accessible(self) -> bool:
256 """Return True. This memory resource provides device-accessible buffers."""
257 return True 1yzsGABCHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,D
259 @property
260 def is_host_accessible(self) -> bool:
261 """Return False. This memory resource does not provide host-accessible buffers."""
262 return False 1yzsABCD
265cdef inline _DMR_init(DeviceMemoryResource self, device_id, options):
266 from .._device import Device 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjc[ kclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLc{ | } ~ a abw bbcbe dbebr fbf gbd E hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbMci j k l b c FbGbHbIbJbNcOcPcQcRcScTcUcVcx y z F s KbG q p t LbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4bWc5bXcYcZc0cm v n o 1c2c3c4c5c6c6b7b7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
267 cdef int dev_id = Device(device_id).device_id 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjc[ kclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLc{ | } ~ a abw bbcbe dbebr fbf gbd E hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbMci j k l b c FbGbHbIbJbNcOcPcQcRcScTcUcVcx y z F s KbG q p t LbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4bWc5bXcYcZc0cm v n o 1c2c3c4c5c6c6b7b7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
268 cdef DeviceMemoryResourceOptions opts = check_or_create_options( 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjc[ kclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLc{ | } ~ a abw bbcbe dbebr fbf gbd E hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbMci j k l b c FbGbHbIbJbNcOcPcQcRcScTcUcVcx y z F s KbG q p t LbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4bWc5bXcYcZc0cm v n o 1c2c3c4c5c6c6b7b7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
269 DeviceMemoryResourceOptions, options, "DeviceMemoryResource options",
270 keep_none=True
271 )
272 cdef bint ipc_enabled = False 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjc[ kclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLc{ | } ~ a abw bbcbe dbebr fbf gbd E hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbMci j k l b c FbGbHbIbJbNcOcPcQcRcScTcUcVcx y z F s KbG q p t LbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4bWc5bXcYcZc0cm v n o 1c2c3c4c5c6c6b7b7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
273 cdef size_t max_size = 0 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjc[ kclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLc{ | } ~ a abw bbcbe dbebr fbf gbd E hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbMci j k l b c FbGbHbIbJbNcOcPcQcRcScTcUcVcx y z F s KbG q p t LbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4bWc5bXcYcZc0cm v n o 1c2c3c4c5c6c6b7b7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
275 self._dev_id = dev_id 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjc[ kclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLc{ | } ~ a abw bbcbe dbebr fbf gbd E hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbMci j k l b c FbGbHbIbJbNcOcPcQcRcScTcUcVcx y z F s KbG q p t LbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4bWc5bXcYcZc0cm v n o 1c2c3c4c5c6c6b7b7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
277 if opts is not None: 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjc[ kclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLc{ | } ~ a abw bbcbe dbebr fbf gbd E hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbMci j k l b c FbGbHbIbJbNcOcPcQcRcScTcUcVcx y z F s KbG q p t LbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4bWc5bXcYcZc0cm v n o 1c2c3c4c5c6c6b7b7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
278 ipc_enabled = opts.ipc_enabled 2[ { | } ~ a abw bbcbe dbebr fbf gbd hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbi j k l b c HbIbJbs KbG q t MbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4b5bm v n o 6b7b
279 if ipc_enabled and not _ipc.is_supported(): 2[ { | } ~ a abw bbcbe dbebr fbf gbd hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbi j k l b c HbIbJbs KbG q t MbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4b5bm v n o 6b7b
280 raise RuntimeError(f"IPC is not available on {platform.system()}")
281 max_size = opts.max_size 2[ { | } ~ a abw bbcbe dbebr fbf gbd hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbi j k l b c HbIbJbs KbG q t MbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4b5bm v n o 6b7b
283 if opts is None: 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjc[ kclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLc{ | } ~ a abw bbcbe dbebr fbf gbd E hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbMci j k l b c FbGbHbIbJbNcOcPcQcRcScTcUcVcx y z F s KbG q p t LbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4bWc5bXcYcZc0cm v n o 1c2c3c4c5c6c6b7b7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
284 self._h_pool = get_device_mempool(dev_id) 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjckclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcE McFbGbNcOcPcQcRcScTcUcVcx y z F q p LbWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
285 if not self._h_pool: 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjckclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcE McFbGbNcOcPcQcRcScTcUcVcx y z F q p LbWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
286 HANDLE_RETURN(get_last_error())
287 raise RuntimeError(
288 f"Failed to initialize DeviceMemoryResource for device {dev_id}: "
289 "cuda-core returned an empty memory pool handle without recording a CUDA error. "
290 "This is an internal cuda-core error; please report it with your CUDA driver, "
291 "CUDA Toolkit, and cuda-python versions."
292 )
293 self._mempool_owned = False 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjckclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcE McFbGbNcOcPcQcRcScTcUcVcx y z F q p LbWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
294 MP_raise_release_threshold(self) 2!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbccc- . / : ; = ? @ dcecfcgchcicjckclcmc] ^ ncocpcqcrcsctc_ ucvc` wcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcE McFbGbNcOcPcQcRcScTcUcVcx y z F q p LbWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cA B C (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c8b9b_cH I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ `c{c|c% ' }c( ) * ~c+ , D
295 else:
296 MP_init_create_pool( 2[ { | } ~ a abw bbcbe dbebr fbf gbd hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbi j k l b c HbIbJbs KbG q t MbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4b5bm v n o 6b7b
297 self,
298 cydriver.CUmemLocationType.CU_MEM_LOCATION_TYPE_DEVICE,
299 dev_id,
300 cydriver.CUmemAllocationType.CU_MEM_ALLOCATION_TYPE_PINNED,
301 ipc_enabled,
302 max_size, 2[ { | } ~ a abw bbcbe dbebr fbf gbd hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbg h CbDbEbi j k l b c HbIbJbs KbG q t MbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bu 4b5bm v n o 6b7b
303 )
306# Note: this is referenced in instructions to debug nvbug 5698116.
307cpdef str DMR_mempool_get_access(DeviceMemoryResource dmr, int device_id):
308 """
309 Probes peer access from the given device using cuMemPoolGetAccess.
311 Parameters
312 ----------
313 device_id : int or Device
314 The device to query access for.
316 Returns
317 -------
318 str
319 Access permissions: "rw" for read-write, "r" for read-only, "" for no access.
320 """
321 from .._device import Device 1p
323 cdef int dev_id = Device(device_id).device_id 1p
324 cdef cydriver.CUmemAccess_flags flags
325 cdef cydriver.CUmemLocation location = cumemlocation_from_id( 1p
326 cydriver.CUmemLocationType.CU_MEM_LOCATION_TYPE_DEVICE, dev_id)
328 with nogil: 1p
329 HANDLE_RETURN(cydriver.cuMemPoolGetAccess(&flags, as_cu(dmr._h_pool), &location)) 1p
331 if flags == cydriver.CUmemAccess_flags.CU_MEM_ACCESS_FLAGS_PROT_READWRITE: 1p
332 return "rw" 1p
333 elif flags == cydriver.CUmemAccess_flags.CU_MEM_ACCESS_FLAGS_PROT_READ:
334 return "r"
335 else:
336 return ""
339def _deep_reduce_device_memory_resource(mr) -> tuple[object, ...]:
340 check_multiprocessing_start_method() 2ada bdcde ddedfdgdhdidjdkdldmdndodpdg h qdrdsdi j k l b c m n o
341 from .._device import Device 2ada bdcde ddedfdgdhdidjdkdldmdndodpdg h qdrdsdi j k l b c m n o
342 device = Device(mr.device_id) 2ada bdcde ddedfdgdhdidjdkdldmdndodpdg h qdrdsdi j k l b c m n o
343 alloc_handle = mr.allocation_handle 2ada bdcde ddedfdgdhdidjdkdldmdndodpdg h qdrdsdi j k l b c m n o
344 return mr.from_allocation_handle, (device, alloc_handle) 2ada bdcde ddedfdgdhdidjdkdldmdndodpdg h qdrdsdi j k l b c m n o
347multiprocessing.reduction.register(DeviceMemoryResource, _deep_reduce_device_memory_resource)