Coverage for cuda/core/_memory/_device_memory_resource.pyx: 85.53%
76 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-03 02:41 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-03 02:41 +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._resource_handles cimport (
15 as_cu,
16 get_device_mempool,
17 get_last_error,
18)
19from cuda.core._utils.cuda_utils cimport (
20 check_or_create_options,
21 HANDLE_RETURN,
22)
24import cython
25from dataclasses import dataclass
26import multiprocessing
27import platform # no-cython-lint
28import uuid
30from cuda.core._memory._peer_access_utils import PeerAccessibleBySetProxy, replace_peer_accessible_by
31from cuda.core._utils.cuda_utils import check_multiprocessing_start_method
33from typing import TYPE_CHECKING
35if TYPE_CHECKING:
36 from cuda.core._device import Device
38__all__ = ['DeviceMemoryResource', 'DeviceMemoryResourceOptions']
41@dataclass
42cdef class DeviceMemoryResourceOptions:
43 """Customizable :obj:`~_memory.DeviceMemoryResource` options.
45 Attributes
46 ----------
47 ipc_enabled : bool, optional
48 Specifies whether to create an IPC-enabled memory pool. When set to
49 True, the memory pool and its allocations can be shared with other
50 processes. (Default to False)
52 max_size : int, optional
53 Maximum pool size. When set to 0, defaults to a system-dependent value.
54 (Default to 0)
55 """
56 ipc_enabled : bool = False
57 max_size : int = 0
60cdef class DeviceMemoryResource(_MemPool):
61 """
62 A device memory resource managing a stream-ordered memory pool.
64 Parameters
65 ----------
66 device_id : Device | int
67 Device or Device ordinal for which a memory resource is constructed.
69 options : DeviceMemoryResourceOptions
70 Memory resource creation options.
72 If set to `None`, the memory resource uses the driver's current
73 stream-ordered memory pool for the specified `device_id`. If no memory
74 pool is set as current, the driver's default memory pool for the device
75 is used.
77 If not set to `None`, a new memory pool is created, which is owned by
78 the memory resource.
80 When using an existing (current or default) memory pool, the returned
81 device memory resource does not own the pool (`is_handle_owned` is
82 `False`), and closing the resource has no effect.
84 Notes
85 -----
86 To create an IPC-Enabled memory resource (MR) that is capable of sharing
87 allocations between processes, specify ``ipc_enabled=True`` in the initializer
88 option. Sharing an allocation is a two-step procedure that involves
89 mapping a memory resource and then mapping buffers owned by that resource.
90 These steps can be accomplished in several ways.
92 An IPC-enabled memory resource can allocate memory buffers but cannot
93 receive shared buffers. Mapping an MR to another process creates a "mapped
94 memory resource" (MMR). An MMR cannot allocate memory buffers and can only
95 receive shared buffers. MRs and MMRs are both of type
96 :class:`DeviceMemoryResource` and can be distinguished via
97 :attr:`DeviceMemoryResource.is_mapped`.
99 An MR is shared via an allocation handle accessed through the
100 :attr:`DeviceMemoryResource.allocation_handle` property. The allocation
101 handle has a platform-specific interpretation; however, memory IPC is
102 currently only supported for Linux, and in that case allocation handles
103 are file descriptors. After sending an allocation handle to another
104 process, it can be used to create an MMR by invoking
105 :meth:`DeviceMemoryResource.from_allocation_handle`.
107 Buffers can be shared as serializable descriptors accessed through the
108 :attr:`Buffer.ipc_descriptor` property. In a receiving process, a shared
109 buffer is created by invoking :meth:`Buffer.from_ipc_descriptor` with an
110 MMR and buffer descriptor, where the MMR corresponds to the MR that
111 created the described buffer.
113 To help manage the association between memory resources and buffers, a
114 registry is provided. Every MR has a unique identifier (UUID). MMRs can be
115 registered by calling :meth:`DeviceMemoryResource.register` with the UUID
116 of the corresponding MR. Registered MMRs can be looked up via
117 :meth:`DeviceMemoryResource.from_registry`. When registering MMRs in this
118 way, the use of buffer descriptors can be avoided. Instead, buffer objects
119 can themselves be serialized and transferred directly. Serialization embeds
120 the UUID, which is used to locate the correct MMR during reconstruction.
122 IPC-enabled memory resources interoperate with the :mod:`multiprocessing`
123 module to provide a simplified interface. This approach can avoid direct
124 use of allocation handles, buffer descriptors, MMRs, and the registry. When
125 using :mod:`multiprocessing` to spawn processes or send objects through
126 communication channels such as :class:`multiprocessing.Queue`,
127 :class:`multiprocessing.Pipe`, or :class:`multiprocessing.Connection`,
128 :class:`Buffer` objects may be sent directly, and in such cases the process
129 for creating MMRs and mapping buffers will be handled automatically.
131 For greater efficiency when transferring many buffers, one may also send
132 MRs and buffers separately. When an MR is sent via :mod:`multiprocessing`,
133 an MMR is created and registered in the receiving process. Subsequently,
134 buffers may be serialized and transferred using ordinary :mod:`pickle`
135 methods. The reconstruction procedure uses the registry to find the
136 associated MMR. Unpickling a :class:`Buffer` performs an IPC import from
137 the embedded descriptor; only unpickle buffers received from trusted peers.
139 Warning
140 -------
141 IPC descriptors and pickled buffers cross a trust boundary between
142 cooperating same-host processes. A malicious peer can supply crafted
143 descriptor fields. Use :meth:`Buffer.from_ipc_descriptor` only with
144 descriptors from trusted peers, and do not unpickle buffers from
145 untrusted sources.
146 """
148 def __cinit__(self, *args, **kwargs) -> None:
149 self._dev_id = cydriver.CU_DEVICE_INVALID 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b4 1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@b9 a ! n # $ d % o ' ( z ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c cbdb[b]b^b_b`bw x y A s ebfbr p t gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zb{bAb|b}b~bk v l m acbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cBbCb1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
151 @cython.annotation_typing(False)
152 def __init__(
153 self,
154 device_id: Device | int,
155 options: DeviceMemoryResourceOptions | None = None
156 ) -> None:
157 _DMR_init(self, device_id, options) 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b4 1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@b9 a ! n # $ d % o ' ( z ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c cbdb[b]b^b_b`bw x y A s ebfbr p t gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zb{bAb|b}b~bk v l m acbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cBbCb1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
159 def __reduce__(self) -> tuple[object, ...]:
160 MP_check_open(self) 1anbc
161 return DeviceMemoryResource.from_registry, (self.uuid,) 1anbc
163 @staticmethod
164 def from_registry(uuid: uuid.UUID) -> DeviceMemoryResource: # no-cython-lint
165 """
166 Obtain a registered mapped memory resource.
168 Raises
169 ------
170 RuntimeError
171 If no mapped memory resource is found in the registry.
172 """
173 return <DeviceMemoryResource>(_ipc.MP_from_registry(uuid)) 1z
175 def register(self, uuid: uuid.UUID) -> DeviceMemoryResource: # no-cython-lint
176 """
177 Register a mapped memory resource.
179 Returns
180 -------
181 The registered mapped memory resource. If one was previously registered
182 with the given key, it is returned.
183 """
184 return <DeviceMemoryResource>(_ipc.MP_register(self, uuid)) 2idz
186 @classmethod
187 def from_allocation_handle(
188 cls, device_id: Device | int, alloc_handle: int | IPCAllocationHandle
189 ) -> DeviceMemoryResource:
190 """Create a device memory resource from an allocation handle.
192 Construct a new `DeviceMemoryResource` instance that imports a memory
193 pool from a shareable handle. The memory pool is marked as owned, and
194 the resource is associated with the specified `device_id`.
196 Parameters
197 ----------
198 device_id : int | Device
199 The ID of the device or a Device object for which the memory
200 resource is created.
202 alloc_handle : int | IPCAllocationHandle
203 The shareable handle of the device memory resource to import. If an
204 integer is supplied, it must represent a valid platform-specific
205 handle. It is the caller's responsibility to close that handle.
207 Returns
208 -------
209 A new device memory resource instance with the imported handle.
210 """
211 cdef DeviceMemoryResource mr = <DeviceMemoryResource>(
212 _ipc.MP_from_allocation_handle(cls, alloc_handle)) 2id
213 from .._device import Device
214 mr._dev_id = Device(device_id).device_id
215 return mr
217 @property
218 def allocation_handle(self) -> IPCAllocationHandle:
219 """Shareable handle for this memory pool (requires IPC).
221 The handle can be used to share the memory pool with other processes.
222 The handle is cached in this `MemoryResource` and owned by it.
223 """
224 MP_check_open(self) 2@ca n [c]cd o id^c_cjdkd`c{cld|c}cmd~cadbdndcdddede f fdgdhdg h i j b c w u k v l m
225 if not self.is_ipc_enabled: 2@ca [c]cd id^c_cjdkd`c{cld|c}cmd~cadbdndcdddede f fdgdhdg h i j b c u k v l m
226 raise RuntimeError("Memory resource is not IPC-enabled") 1u
227 return self._ipc_data._alloc_handle 2@ca [c]cd id^c_cjdkd`c{cld|c}cmd~cadbdndcdddede f fdgdhdg h i j b c k v l m
229 @property
230 def device_id(self) -> int:
231 """The associated device ordinal."""
232 return self._dev_id 2W X Y Z 0 1 2 3 EdFd5 6 Gd7 Hd8 IdJdKdLd@ca n [c]cd o ^c_c`c{c|c}c~cadbdcdddede f fdgdhdg h i j b c cbdbx y s gbk l m odpdB C D E qdF G H I rdJ sdK L tdM udN vdO P wdQ xdR ydS zdAdT BdCdU V Dd
234 @property
235 def peer_accessible_by(self) -> PeerAccessibleBySetProxy:
236 """
237 Get or set the devices that can access allocations from this memory
238 pool. Access can be modified at any time and affects all allocations
239 from this memory pool.
241 Returns a set-like proxy of :obj:`~_device.Device` objects that manages
242 peer access. Inputs are accepted as either :obj:`~_device.Device`
243 objects or device-ordinal :class:`int` values.
245 Examples
246 --------
247 >>> dmr = DeviceMemoryResource(0)
248 >>> dmr.peer_accessible_by = {1} # grant access to device 1
249 >>> assert 1 in dmr.peer_accessible_by
250 >>> dmr.peer_accessible_by.add(2) # update access to include device 2
251 >>> dmr.peer_accessible_by = [] # revoke peer access
252 """
253 MP_check_open(self) 1wAt
254 return PeerAccessibleBySetProxy(self) 1wAt
256 @peer_accessible_by.setter
257 def peer_accessible_by(self, devices) -> None:
258 replace_peer_accessible_by(self, devices) 1t
260 @property
261 def is_device_accessible(self) -> bool:
262 """Return True. This memory resource provides device-accessible buffers."""
263 return True 2x y s odpdB C D E qdF G H I rdJ sdK L tdM udN vdO P wdQ xdR ydS zdAdT BdCdU V Dd
265 @property
266 def is_host_accessible(self) -> bool:
267 """Return False. This memory resource does not provide host-accessible buffers."""
268 return False 1xys
271cdef inline _DMR_init(DeviceMemoryResource self, device_id, options):
272 from .._device import Device 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b4 1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@b9 a ! n # $ d % o ' ( z ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c cbdb[b]b^b_b`bw x y A s ebfbr p t gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zb{bAb|b}b~bk v l m acbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cBbCb1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
273 cdef int dev_id = Device(device_id).device_id 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b4 1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@b9 a ! n # $ d % o ' ( z ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c cbdb[b]b^b_b`bw x y A s ebfbr p t gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zb{bAb|b}b~bk v l m acbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cBbCb1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
274 cdef DeviceMemoryResourceOptions opts = check_or_create_options( 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b4 1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@b9 a ! n # $ d % o ' ( z ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c cbdb[b]b^b_b`bw x y A s ebfbr p t gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zb{bAb|b}b~bk v l m acbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cBbCb1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
275 DeviceMemoryResourceOptions, options, "DeviceMemoryResource options",
276 keep_none=True
277 )
278 cdef bint ipc_enabled = False 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b4 1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@b9 a ! n # $ d % o ' ( z ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c cbdb[b]b^b_b`bw x y A s ebfbr p t gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zb{bAb|b}b~bk v l m acbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cBbCb1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
279 cdef size_t max_size = 0 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b4 1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@b9 a ! n # $ d % o ' ( z ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c cbdb[b]b^b_b`bw x y A s ebfbr p t gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zb{bAb|b}b~bk v l m acbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cBbCb1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
281 self._dev_id = dev_id 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b4 1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@b9 a ! n # $ d % o ' ( z ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c cbdb[b]b^b_b`bw x y A s ebfbr p t gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zb{bAb|b}b~bk v l m acbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cBbCb1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
283 if opts is not None: 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b4 1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@b9 a ! n # $ d % o ' ( z ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c cbdb[b]b^b_b`bw x y A s ebfbr p t gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zb{bAb|b}b~bk v l m acbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cBbCb1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
284 ipc_enabled = opts.ipc_enabled 24 9 a ! n # $ d % o ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c s ebfbr t hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zbAbk v l m BbCb
285 if ipc_enabled and not _ipc.is_supported(): 24 9 a ! n # $ d % o ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c s ebfbr t hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zbAbk v l m BbCb
286 raise RuntimeError(f"IPC is not available on {platform.system()}")
287 max_size = opts.max_size 24 9 a ! n # $ d % o ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c s ebfbr t hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zbAbk v l m BbCb
289 if opts is None: 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b4 1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@b9 a ! n # $ d % o ' ( z ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c cbdb[b]b^b_b`bw x y A s ebfbr p t gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zb{bAb|b}b~bk v l m acbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cBbCb1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
290 self._h_pool = get_device_mempool(dev_id) 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@bz cbdb[b]b^b_b`bw x y A r p gb{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
291 if not self._h_pool: 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@bz cbdb[b]b^b_b`bw x y A r p gb{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
292 HANDLE_RETURN(get_last_error())
293 raise RuntimeError(
294 f"Failed to initialize DeviceMemoryResource for device {dev_id}: "
295 "cuda-core returned an empty memory pool handle without recording a CUDA error. "
296 "This is an internal cuda-core error; please report it with your CUDA driver, "
297 "CUDA Toolkit, and cuda-python versions."
298 )
299 self._mempool_owned = False 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@bz cbdb[b]b^b_b`bw x y A r p gb{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
300 MP_raise_release_threshold(self) 2DbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbW X Y Z 0 1 2 3 Zb0b1b2b3b5 6 4b5b6b7b8b9b!b7 #b$b8 %b'b(b)b*b+b,b-b.b/b:b;b=b?b@bz cbdb[b]b^b_b`bw x y A r p gb{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=cB C D E F G H I J K L M N O P Q R S T ?cU V
301 else:
302 MP_init_create_pool( 24 9 a ! n # $ d % o ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c s ebfbr t hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zbAbk v l m BbCb
303 self,
304 cydriver.CUmemLocationType.CU_MEM_LOCATION_TYPE_DEVICE,
305 dev_id,
306 cydriver.CUmemAllocationType.CU_MEM_ALLOCATION_TYPE_PINNED,
307 ipc_enabled,
308 max_size, 24 9 a ! n # $ d % o ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } e f ~ abbbg h i j b c s ebfbr t hbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybu zbAbk v l m BbCb
309 )
312# Note: this is referenced in instructions to debug nvbug 5698116.
313cpdef str DMR_mempool_get_access(DeviceMemoryResource dmr, int device_id):
314 """
315 Probes peer access from the given device using cuMemPoolGetAccess.
317 Parameters
318 ----------
319 device_id : int or Device
320 The device to query access for.
322 Returns
323 -------
324 str
325 Access permissions: "rw" for read-write, "r" for read-only, "" for no access.
326 """
327 from .._device import Device 1p
329 cdef int dev_id = Device(device_id).device_id 1p
330 cdef cydriver.CUmemAccess_flags flags
331 cdef cydriver.CUmemLocation location = cumemlocation_from_id( 1p
332 cydriver.CUmemLocationType.CU_MEM_LOCATION_TYPE_DEVICE, dev_id)
334 with nogil: 1p
335 HANDLE_RETURN(cydriver.cuMemPoolGetAccess(&flags, as_cu(dmr._h_pool), &location)) 1p
337 if flags == cydriver.CUmemAccess_flags.CU_MEM_ACCESS_FLAGS_PROT_READWRITE: 1p
338 return "rw" 1p
339 elif flags == cydriver.CUmemAccess_flags.CU_MEM_ACCESS_FLAGS_PROT_READ:
340 return "r"
341 else:
342 return ""
345def _deep_reduce_device_memory_resource(mr) -> tuple[object, ...]:
346 check_multiprocessing_start_method() 2@ca n [c]cd o ^c_c`c{c|c}c~cadbdcdddede f fdgdhdg h i j b c k l m
347 from .._device import Device 2@ca n [c]cd o ^c_c`c{c|c}c~cadbdcdddede f fdgdhdg h i j b c k l m
348 device = Device(mr.device_id) 2@ca n [c]cd o ^c_c`c{c|c}c~cadbdcdddede f fdgdhdg h i j b c k l m
349 alloc_handle = mr.allocation_handle 2@ca n [c]cd o ^c_c`c{c|c}c~cadbdcdddede f fdgdhdg h i j b c k l m
350 return mr.from_allocation_handle, (device, alloc_handle) 2@ca [c]cd ^c_c`c{c|c}c~cadbdcdddede f fdgdhdg h i j b c k l m
353multiprocessing.reduction.register(DeviceMemoryResource, _deep_reduce_device_memory_resource)