Coverage for cuda/core/_memory/_device_memory_resource.pyx: 63.29%
79 statements
« prev ^ index » next coverage.py v7.17.2, created at 2026-11-05 01:11 +0000
« prev ^ index » next coverage.py v7.17.2, created at 2026-11-05 01:11 +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, for the device
129 with the same UUID as the MR's device, whatever its ordinal is there; if
130 that device is not visible, unpickling raises ``RuntimeError``. Subsequently,
131 buffers may be serialized and transferred using ordinary :mod:`pickle`
132 methods. The reconstruction procedure uses the registry to find the
133 associated MMR. Unpickling a :class:`Buffer` performs an IPC import from
134 the embedded descriptor; only unpickle buffers received from trusted peers.
136 Warning
137 -------
138 IPC descriptors and pickled buffers cross a trust boundary between
139 cooperating same-host processes. A malicious peer can supply crafted
140 descriptor fields. Use :meth:`Buffer.from_ipc_descriptor` only with
141 descriptors from trusted peers, and do not unpickle buffers from
142 untrusted sources.
143 """
145 def __cinit__(self, *args, **kwargs) -> None:
146 self._dev_id = cydriver.CU_DEVICE_INVALID 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyc] zcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c| } ~ aba bbw cbdbe ebfbr gbf hbd ibF jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGb1ci j k l b c HbIb2c3c4cJbKbLb5c6c7c8cMb9c!c#c$c%c'c(c)cx y z NbG s ObH q p t PbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b*c,b+c,c-c.cm v n o /c:c;c=c?c@c-b.b[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
148 def __init__(
149 self,
150 device_id: Device | int,
151 options: DeviceMemoryResourceOptions | None = None
152 ) -> None:
153 _DMR_init(self, device_id, options) 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyc] zcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c| } ~ aba bbw cbdbe ebfbr gbf hbd ibF jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGb1ci j k l b c HbIb2c3c4cJbKbLb5c6c7c8cMb9c!c#c$c%c'c(c)cx y z NbG s ObH q p t PbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b*c,b+c,c-c.cm v n o /c:c;c=c?c@c-b.b[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
155 def __reduce__(self) -> tuple[object, ...]:
156 MP_check_open(self) 1awbc
157 return DeviceMemoryResource.from_registry, (self.uuid,) 1awbc
159 @staticmethod
160 def from_registry(uuid: uuid.UUID) -> DeviceMemoryResource: # no-cython-lint
161 """
162 Obtain a registered mapped memory resource.
164 Raises
165 ------
166 RuntimeError
167 If no mapped memory resource is found in the registry.
168 """
169 return <DeviceMemoryResource>(_ipc.MP_from_registry(uuid)) 1dF
171 def register(self, uuid: uuid.UUID) -> DeviceMemoryResource: # no-cython-lint
172 """
173 Register a mapped memory resource.
175 Returns
176 -------
177 The registered mapped memory resource. If one was previously registered
178 with the given key, it is returned.
180 Raises
181 ------
182 RuntimeError
183 If the memory resource is not IPC-enabled.
184 ValueError
185 If the memory resource already has a different UUID.
186 """
187 return <DeviceMemoryResource>(_ipc.MP_register(self, uuid)) 2Tdd ZdF
189 @classmethod
190 def from_allocation_handle(
191 cls, device_id: Device | int, alloc_handle: int | IPCAllocationHandle
192 ) -> DeviceMemoryResource:
193 """Create a device memory resource from an allocation handle.
195 Construct a new `DeviceMemoryResource` instance that imports a memory
196 pool from a shareable handle. The memory pool is marked as owned, and
197 the resource is associated with the specified `device_id`.
199 Parameters
200 ----------
201 device_id : int | Device
202 The ID of the device or a Device object for which the memory
203 resource is created.
205 alloc_handle : int | IPCAllocationHandle
206 The shareable handle of the device memory resource to import. If an
207 integer is supplied, it must represent a valid platform-specific
208 handle. It is the caller's responsibility to close that handle.
210 Returns
211 -------
212 A new device memory resource instance with the imported handle.
213 """
214 cdef DeviceMemoryResource mr = <DeviceMemoryResource>( 1fd
215 _ipc.MP_from_allocation_handle(cls, alloc_handle)) 2Tdf d
216 from .._device import Device 1fd
217 mr._dev_id = Device(device_id).device_id 1fd
218 return mr 1fd
220 @property
221 def allocation_handle(self) -> IPCAllocationHandle:
222 """Shareable handle for this memory pool (requires IPC).
224 The handle can be used to share the memory pool with other processes.
225 The handle is cached in this `MemoryResource` and owned by it.
226 """
227 MP_check_open(self) 2Ada BdCde r Tdf d DdEdFdUdVdGdHdWdIdJdXdKdLdMdYdNdOdPdg h QdRdSdi j k l b c x u m v n o
228 if not self.is_ipc_enabled: 2Ada BdCde r Tdf d DdEdFdUdVdGdHdWdIdJdXdKdLdMdYdNdOdPdg h QdRdSdi j k l b c u m v n o
229 raise RuntimeError("Memory resource is not IPC-enabled") 1u
230 return self._ipc_data._alloc_handle 2Ada BdCde r Tdf d DdEdFdUdVdGdHdWdIdJdXdKdLdMdYdNdOdPdg h QdRdSdi j k l b c m v n o
232 @property
233 def device_id(self) -> int:
234 """The associated device ordinal."""
235 return self._dev_id 2. / : ; = ? @ [ 0d1d^ _ 2d` 3d{ 4d5d6d7dAda BdCde f DdEdFdGdHdIdJdKdLdMdNdOdPdg h QdRdSdi j k l b c HbIby z s Pbm n o A B C D /b:bI 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 ! # $ % ' ( ) * + , - E
237 @property
238 def peer_accessible_by(self) -> PeerAccessibleBySetProxy:
239 """
240 Get or set the devices that can access allocations from this memory
241 pool. Access can be modified at any time and affects all allocations
242 from this memory pool.
244 Returns a set-like proxy of :obj:`~_device.Device` objects that manages
245 peer access. Inputs are accepted as either :obj:`~_device.Device`
246 objects or device-ordinal :class:`int` values.
248 Examples
249 --------
250 >>> dmr = DeviceMemoryResource(0)
251 >>> dmr.peer_accessible_by = {1} # grant access to device 1
252 >>> assert 1 in dmr.peer_accessible_by
253 >>> dmr.peer_accessible_by.add(2) # update access to include device 2
254 >>> dmr.peer_accessible_by = [] # revoke peer access
255 """
256 MP_check_open(self) 1xGt
257 return PeerAccessibleBySetProxy(self) 1xGt
259 @peer_accessible_by.setter
260 def peer_accessible_by(self, devices) -> None:
261 replace_peer_accessible_by(self, devices) 1t
263 @property
264 def is_device_accessible(self) -> bool:
265 """Return True. This memory resource provides device-accessible buffers."""
266 return True 1yzsHABCDIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-E
268 @property
269 def is_host_accessible(self) -> bool:
270 """Return False. This memory resource does not provide host-accessible buffers."""
271 return False 2Mby z s A B C D E
274cdef inline _DMR_init(DeviceMemoryResource self, device_id, options):
275 from .._device import Device 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyc] zcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c| } ~ aba bbw cbdbe ebfbr gbf hbd ibF jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGb1ci j k l b c HbIb2c3c4cJbKbLb5c6c7c8cMb9c!c#c$c%c'c(c)cx y z NbG s ObH q p t PbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b*c,b+c,c-c.cm v n o /c:c;c=c?c@c-b.b[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
276 cdef int dev_id = Device(device_id).device_id 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyc] zcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c| } ~ aba bbw cbdbe ebfbr gbf hbd ibF jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGb1ci j k l b c HbIb2c3c4cJbKbLb5c6c7c8cMb9c!c#c$c%c'c(c)cx y z NbG s ObH q p t PbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b*c,b+c,c-c.cm v n o /c:c;c=c?c@c-b.b[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
277 cdef DeviceMemoryResourceOptions opts = check_or_create_options( 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyc] zcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c| } ~ aba bbw cbdbe ebfbr gbf hbd ibF jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGb1ci j k l b c HbIb2c3c4cJbKbLb5c6c7c8cMb9c!c#c$c%c'c(c)cx y z NbG s ObH q p t PbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b*c,b+c,c-c.cm v n o /c:c;c=c?c@c-b.b[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
278 DeviceMemoryResourceOptions, options, "DeviceMemoryResource options",
279 keep_none=True
280 )
281 cdef bint ipc_enabled = False 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyc] zcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c| } ~ aba bbw cbdbe ebfbr gbf hbd ibF jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGb1ci j k l b c HbIb2c3c4cJbKbLb5c6c7c8cMb9c!c#c$c%c'c(c)cx y z NbG s ObH q p t PbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b*c,b+c,c-c.cm v n o /c:c;c=c?c@c-b.b[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
282 cdef size_t max_size = 0 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyc] zcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c| } ~ aba bbw cbdbe ebfbr gbf hbd ibF jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGb1ci j k l b c HbIb2c3c4cJbKbLb5c6c7c8cMb9c!c#c$c%c'c(c)cx y z NbG s ObH q p t PbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b*c,b+c,c-c.cm v n o /c:c;c=c?c@c-b.b[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
284 self._dev_id = dev_id 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyc] zcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c| } ~ aba bbw cbdbe ebfbr gbf hbd ibF jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGb1ci j k l b c HbIb2c3c4cJbKbLb5c6c7c8cMb9c!c#c$c%c'c(c)cx y z NbG s ObH q p t PbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b*c,b+c,c-c.cm v n o /c:c;c=c?c@c-b.b[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
286 if opts is not None: 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyc] zcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c| } ~ aba bbw cbdbe ebfbr gbf hbd ibF jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGb1ci j k l b c HbIb2c3c4cJbKbLb5c6c7c8cMb9c!c#c$c%c'c(c)cx y z NbG s ObH q p t PbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b*c,b+c,c-c.cm v n o /c:c;c=c?c@c-b.b[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
287 ipc_enabled = opts.ipc_enabled 2] | } ~ aba bbw cbdbe ebfbr gbf hbd ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGbi j k l b c JbKbLbNbs ObH q t QbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b,bm v n o -b.b
288 if ipc_enabled and not _ipc.is_supported(): 2] | } ~ aba bbw cbdbe ebfbr gbf hbd ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGbi j k l b c JbKbLbNbs ObH q t QbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b,bm v n o -b.b
289 raise RuntimeError(f"IPC is not available on {platform.system()}")
290 max_size = opts.max_size 2] | } ~ aba bbw cbdbe ebfbr gbf hbd ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGbi j k l b c JbKbLbNbs ObH q t QbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b,bm v n o -b.b
292 if opts is None: 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyc] zcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c| } ~ aba bbw cbdbe ebfbr gbf hbd ibF jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGb1ci j k l b c HbIb2c3c4cJbKbLb5c6c7c8cMb9c!c#c$c%c'c(c)cx y z NbG s ObH q p t PbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b*c,b+c,c-c.cm v n o /c:c;c=c?c@c-b.b[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
293 self._h_pool = get_device_mempool(dev_id) 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyczcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cF 1cHbIb2c3c4c5c6c7c8cMb9c!c#c$c%c'c(c)cx y z G q p Pb*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
294 if not self._h_pool: 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyczcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cF 1cHbIb2c3c4c5c6c7c8cMb9c!c#c$c%c'c(c)cx y z G q p Pb*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
295 HANDLE_RETURN(get_last_error())
296 raise RuntimeError(
297 f"Failed to initialize DeviceMemoryResource for device {dev_id}: "
298 "cuda-core returned an empty memory pool handle without recording a CUDA error. "
299 "This is an internal cuda-core error; please report it with your CUDA driver, "
300 "CUDA Toolkit, and cuda-python versions."
301 )
302 self._mempool_owned = False 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyczcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cF 1cHbIb2c3c4c5c6c7c8cMb9c!c#c$c%c'c(c)cx y z G q p Pb*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
303 MP_raise_release_threshold(self) 2;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqc. / : ; = ? @ [ rcsctcucvcwcxcyczcAcBc^ _ CcDcEcFcGcHcIc` JcKc{ LcMcNcOcPcQcRcScTcUcVcWcXcYcZc0cF 1cHbIb2c3c4c5c6c7c8cMb9c!c#c$c%c'c(c)cx y z G q p Pb*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadA B C bdcdddD edfdgdhdidjdkdldmdndodpdqdrdsdtd/b:budI 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 ! # $ % vdwdxd' ( yd) * + zd, - E
304 else:
305 MP_init_create_pool( 2] | } ~ aba bbw cbdbe ebfbr gbf hbd ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGbi j k l b c JbKbLbNbs ObH q t QbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b,bm v n o -b.b
306 self,
307 cydriver.CUmemLocationType.CU_MEM_LOCATION_TYPE_DEVICE,
308 dev_id,
309 cydriver.CUmemAllocationType.CU_MEM_ALLOCATION_TYPE_PINNED,
310 ipc_enabled,
311 max_size, 2] | } ~ aba bbw cbdbe ebfbr gbf hbd ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbg h EbFbGbi j k l b c JbKbLbNbs ObH q t QbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#bu $b%b'b(b)b*b+b,bm v n o -b.b
312 )
315# Note: this is referenced in instructions to debug nvbug 5698116.
316cpdef str DMR_mempool_get_access(DeviceMemoryResource dmr, int device_id):
317 """
318 Probes peer access from the given device using cuMemPoolGetAccess.
320 Parameters
321 ----------
322 device_id : int or Device
323 The device to query access for.
325 Returns
326 -------
327 str
328 Access permissions: "rw" for read-write, "r" for read-only, "" for no access.
329 """
330 from .._device import Device 1p
332 cdef int dev_id = Device(device_id).device_id 1p
333 cdef cydriver.CUmemAccess_flags flags
334 cdef cydriver.CUmemLocation location = cumemlocation_from_id( 1p
335 cydriver.CUmemLocationType.CU_MEM_LOCATION_TYPE_DEVICE, dev_id)
337 with nogil: 1p
338 HANDLE_RETURN(cydriver.cuMemPoolGetAccess(&flags, as_cu(dmr._h_pool), &location)) 1p
340 if flags == cydriver.CUmemAccess_flags.CU_MEM_ACCESS_FLAGS_PROT_READWRITE: 1p
341 return "rw" 1p
342 elif flags == cydriver.CUmemAccess_flags.CU_MEM_ACCESS_FLAGS_PROT_READ:
343 return "r"
344 else:
345 return ""
348def _deep_reduce_device_memory_resource(mr) -> tuple[object, ...]:
349 check_multiprocessing_start_method() 2Ada BdCde DdEdFdGdHdIdJdKdLdMdNdOdPdg h QdRdSdi j k l b c m n o
350 from .._device import Device 2Ada BdCde DdEdFdGdHdIdJdKdLdMdNdOdPdg h QdRdSdi j k l b c m n o
351 # Device ordinals are per process; the receiver maps the UUID to its own device.
352 device_uuid = Device(mr.device_id).uuid 2Ada BdCde DdEdFdGdHdIdJdKdLdMdNdOdPdg h QdRdSdi j k l b c m n o
353 alloc_handle = mr.allocation_handle 2Ada BdCde DdEdFdGdHdIdJdKdLdMdNdOdPdg h QdRdSdi j k l b c m n o
354 return _reconstruct_device_memory_resource, (type(mr), device_uuid, alloc_handle) 2Ada BdCde DdEdFdGdHdIdJdKdLdMdNdOdPdg h QdRdSdi j k l b c m n o
357def _reconstruct_device_memory_resource(
358 cls: type, device_uuid: str, IPCAllocationHandle alloc_handle not None: IPCAllocationHandle
359) -> DeviceMemoryResource:
360 from .._device import _device_from_uuid
361 return cls.from_allocation_handle(_device_from_uuid(device_uuid), alloc_handle)
364multiprocessing.reduction.register(DeviceMemoryResource, _deep_reduce_device_memory_resource)