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

1# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 

2# 

3# SPDX-License-Identifier: Apache-2.0 

4  

5from __future__ import annotations 

6  

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) 

19  

20from dataclasses import dataclass 

21import multiprocessing 

22import platform # no-cython-lint 

23import uuid 

24  

25from cuda.core._memory._peer_access_utils import PeerAccessibleBySetProxy, replace_peer_accessible_by 

26from cuda.core._utils.cuda_utils import check_multiprocessing_start_method 

27  

28from typing import TYPE_CHECKING 

29  

30if TYPE_CHECKING: 

31 from cuda.core._device import Device 

32  

33__all__ = ['DeviceMemoryResource', 'DeviceMemoryResourceOptions'] 

34  

35  

36@dataclass 

37cdef class DeviceMemoryResourceOptions: 

38 """Customizable :obj:`~_memory.DeviceMemoryResource` options. 

39  

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) 

46  

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 

53  

54  

55cdef class DeviceMemoryResource(_MemPool): 

56 """ 

57 A device memory resource managing a stream-ordered memory pool. 

58  

59 Parameters 

60 ---------- 

61 device_id : Device | int 

62 Device or Device ordinal for which a memory resource is constructed. 

63  

64 options : DeviceMemoryResourceOptions 

65 Memory resource creation options. 

66  

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. 

71  

72 If not set to `None`, a new memory pool is created, which is owned by 

73 the memory resource. 

74  

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. 

78  

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. 

86  

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`. 

93  

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`. 

101  

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. 

107  

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. 

116  

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. 

125  

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. 

133  

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 """ 

142  

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

145  

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

152  

153 def __reduce__(self) -> tuple[object, ...]: 

154 MP_check_open(self) 1awbc

155 return DeviceMemoryResource.from_registry, (self.uuid,) 1awbc

156  

157 @staticmethod 

158 def from_registry(uuid: uuid.UUID) -> DeviceMemoryResource: # no-cython-lint 

159 """ 

160 Obtain a registered mapped memory resource. 

161  

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

168  

169 def register(self, uuid: uuid.UUID) -> DeviceMemoryResource: # no-cython-lint 

170 """ 

171 Register a mapped memory resource. 

172  

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

179  

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. 

185  

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`. 

189  

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. 

195  

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. 

200  

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

210  

211 @property 

212 def allocation_handle(self) -> IPCAllocationHandle: 

213 """Shareable handle for this memory pool (requires IPC). 

214  

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

222  

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

227  

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. 

234  

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. 

238  

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

249  

250 @peer_accessible_by.setter 

251 def peer_accessible_by(self, devices) -> None: 

252 replace_peer_accessible_by(self, devices) 1t

253  

254 @property 

255 def is_device_accessible(self) -> bool: 

256 """Return True. This memory resource provides device-accessible buffers.""" 

257 return True 1yzsGABCHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,D

258  

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

263  

264  

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

274  

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

276  

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

282  

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 ) 

304  

305  

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. 

310  

311 Parameters 

312 ---------- 

313 device_id : int or Device 

314 The device to query access for. 

315  

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

322  

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) 

327  

328 with nogil: 1p

329 HANDLE_RETURN(cydriver.cuMemPoolGetAccess(&flags, as_cu(dmr._h_pool), &location)) 1p

330  

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 "" 

337  

338  

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

345  

346  

347multiprocessing.reduction.register(DeviceMemoryResource, _deep_reduce_device_memory_resource)