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

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

135  

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

144  

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

147  

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

154  

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

156 MP_check_open(self) 1awbc

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

158  

159 @staticmethod 

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

161 """ 

162 Obtain a registered mapped memory resource. 

163  

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

170  

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

172 """ 

173 Register a mapped memory resource. 

174  

175 Returns 

176 ------- 

177 The registered mapped memory resource. If one was previously registered 

178 with the given key, it is returned. 

179  

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

188  

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. 

194  

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

198  

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. 

204  

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. 

209  

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

219  

220 @property 

221 def allocation_handle(self) -> IPCAllocationHandle: 

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

223  

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

231  

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

236  

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. 

243  

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. 

247  

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

258  

259 @peer_accessible_by.setter 

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

261 replace_peer_accessible_by(self, devices) 1t

262  

263 @property 

264 def is_device_accessible(self) -> bool: 

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

266 return True 1yzsHABCDIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-E

267  

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

272  

273  

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

283  

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

285  

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

291  

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 ) 

313  

314  

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. 

319  

320 Parameters 

321 ---------- 

322 device_id : int or Device 

323 The device to query access for. 

324  

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

331  

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) 

336  

337 with nogil: 1p

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

339  

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

346  

347  

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

355  

356  

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) 

362  

363  

364multiprocessing.reduction.register(DeviceMemoryResource, _deep_reduce_device_memory_resource)