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

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._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) 

23  

24import cython 

25from dataclasses import dataclass 

26import multiprocessing 

27import platform # no-cython-lint 

28import uuid 

29  

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

31from cuda.core._utils.cuda_utils import check_multiprocessing_start_method 

32  

33from typing import TYPE_CHECKING 

34  

35if TYPE_CHECKING: 

36 from cuda.core._device import Device 

37  

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

39  

40  

41@dataclass 

42cdef class DeviceMemoryResourceOptions: 

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

44  

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) 

51  

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 

58  

59  

60cdef class DeviceMemoryResource(_MemPool): 

61 """ 

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

63  

64 Parameters 

65 ---------- 

66 device_id : Device | int 

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

68  

69 options : DeviceMemoryResourceOptions 

70 Memory resource creation options. 

71  

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. 

76  

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

78 the memory resource. 

79  

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. 

83  

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. 

91  

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

98  

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

106  

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. 

112  

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. 

121  

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. 

130  

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. 

138  

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

147  

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

150  

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

158  

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

160 MP_check_open(self) 1anbc

161 return DeviceMemoryResource.from_registry, (self.uuid,) 1anbc

162  

163 @staticmethod 

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

165 """ 

166 Obtain a registered mapped memory resource. 

167  

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

174  

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

176 """ 

177 Register a mapped memory resource. 

178  

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

185  

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. 

191  

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

195  

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. 

201  

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. 

206  

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 

216  

217 @property 

218 def allocation_handle(self) -> IPCAllocationHandle: 

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

220  

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

228  

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

233  

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. 

240  

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. 

244  

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

255  

256 @peer_accessible_by.setter 

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

258 replace_peer_accessible_by(self, devices) 1t

259  

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

264  

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

269  

270  

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

280  

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

282  

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

288  

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 ) 

310  

311  

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. 

316  

317 Parameters 

318 ---------- 

319 device_id : int or Device 

320 The device to query access for. 

321  

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

328  

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) 

333  

334 with nogil: 1p

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

336  

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

343  

344  

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

351  

352  

353multiprocessing.reduction.register(DeviceMemoryResource, _deep_reduce_device_memory_resource)