Coverage for cuda/core/_memory/_buffer.pyx: 88.79%
214 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-29 01:38 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-29 01:38 +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
7cimport cython
8from libc.stdint cimport uintptr_t
9from libcpp.atomic cimport memory_order_acquire, memory_order_release
11from cuda.bindings cimport cydriver
12from cuda.core._memory._device_memory_resource import DeviceMemoryResource
13from cuda.core._memory._pinned_memory_resource import PinnedMemoryResource
14from cuda.core._memory._ipc cimport IPCBufferDescriptor, IPCDataForBuffer
15from cuda.core._memory cimport _ipc
16from cuda.core._resource_handles cimport (
17 DevicePtrHandle,
18 StreamHandle,
19 deviceptr_create_with_owner,
20 deviceptr_create_with_mr,
21 register_mr_dealloc_callback,
22 as_intptr,
23 as_cu,
24 set_deallocation_stream,
25)
26from cuda.core.typing import DevicePointerType
28from cuda.core._stream cimport Stream, Stream_accept, default_stream
29from cuda.core._utils.cuda_utils cimport HANDLE_RETURN, _parse_fill_value
31import sys
32from typing import TYPE_CHECKING
34from cuda.core._utils.pycompat import BufferProtocol
35from cuda.core._dlpack import classify_dl_device, make_py_capsule
36from cuda.core._device import Device
38if TYPE_CHECKING:
39 from cuda.core.graph import GraphBuilder
42# =============================================================================
43# MR deallocation callback (invoked from C++ shared_ptr deleter)
44# =============================================================================
46cdef void _mr_dealloc_callback(
47 object mr,
48 cydriver.CUdeviceptr ptr,
49 size_t size,
50 const StreamHandle& h_stream,
51) noexcept:
52 """Called by the C++ deleter to deallocate via MemoryResource.deallocate.
54 This is the C++ teardown path: there is no Python caller frame from
55 which to obtain a stream. If the device-pointer handle was created
56 without ``set_deallocation_stream`` being called (e.g. buffers minted
57 via ``Buffer.from_handle(ptr, size, mr=mr)`` from DLPack import,
58 third-party adapters, or other foreign sources), ``h_stream`` is
59 empty here. Stream-ordered MR ``deallocate`` overrides reject
60 ``stream=None`` (issue #2001), so without a fallback the destructor
61 would print a warning and leak the allocation. Fall back to the
62 legacy/per-thread default stream so the free still happens; this is
63 the unique exception to the "no implicit default-stream fallback"
64 policy because the teardown has no other source of truth.
65 """
66 cdef Stream stream
67 try: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M }fN O P Q R S 1 ~f| } ~ abpbqbrbsbtbubvbT U V /f:f;f=f?fSc@f[f]fbb^f_f2 xdDbEbFbGbcbHbIbddedebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncW X VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/c@c[cOcPcNcQcd e f
68 stream = Stream._from_handle(Stream, h_stream) if h_stream else default_stream() 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M }fN O P Q R S 1 ~f| } ~ abpbqbrbsbtbubvbT U V /f:f;f=f?fSc@f[f]fbb^f_f2 xdDbEbFbGbcbHbIbddedebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncW X VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/c@c[cOcPcNcQcd e f
69 mr.deallocate(int(ptr), size, stream=stream) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M }fN O P Q R S 1 ~f| } ~ abpbqbrbsbtbubvbT U V /f:f;f=f?fSc@f[f]fbb^f_f2 xdDbEbFbGbcbHbIbddedebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncW X VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/c@c[cOcPcNcQcd e f
70 except Exception as exc: 2Nc
71 print(f"Warning: mr.deallocate() failed during Buffer destruction: {exc}", 2Nc
72 file=sys.stderr) 2Nc
74register_mr_dealloc_callback(_mr_dealloc_callback)
77__all__ = ['Buffer', 'MemoryResource']
80# Memory Attribute Query Helpers
81# ------------------------------
82cdef inline int _query_memory_attrs(
83 _MemAttrs& out,
84 cydriver.CUdeviceptr ptr
85) except -1 nogil:
86 """Query memory attributes for a device pointer."""
87 cdef unsigned int memory_type = 0 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
88 cdef int is_managed = 0 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
89 cdef int device_id = 0 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
90 cdef cydriver.CUpointer_attribute[3] attrs = [ 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
91 cydriver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_MEMORY_TYPE,
92 cydriver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_IS_MANAGED,
93 cydriver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL,
94 ]
95 cdef uintptr_t[3] vals = [ 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
96 <uintptr_t><void*>&memory_type,
97 <uintptr_t><void*>&is_managed,
98 <uintptr_t><void*>&device_id,
99 ]
101 cdef cydriver.CUresult ret
102 ret = cydriver.cuPointerGetAttributes(3, attrs, <void**>vals, ptr) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
103 if ret == cydriver.CUresult.CUDA_ERROR_NOT_INITIALIZED: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
104 with cython.gil:
105 # Device class handles the cuInit call internally
106 Device()
107 ret = cydriver.cuPointerGetAttributes(3, attrs, <void**>vals, ptr)
108 HANDLE_RETURN(ret) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
110 # TODO: HMM/ATS-enabled sysmem should also report is_managed=True; the
111 # CU_POINTER_ATTRIBUTE_IS_MANAGED query does not capture that yet.
112 out.is_managed = is_managed != 0 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
114 if memory_type == 0: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
115 # unregistered host pointer
116 out.is_host_accessible = True 2dbY Z KbLbMbNbObPbQbRbSbTb
117 out.is_device_accessible = False 2dbY Z KbLbMbNbObPbQbRbSbTb
118 out.device_id = -1 2dbY Z KbLbMbNbObPbQbRbSbTb
119 elif ( 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h AbBbW X Y Z { mbobCbd e f 0
120 is_managed 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h AbBbW X Y Z { mbobCbd e f 0
121 or memory_type == cydriver.CUmemorytype.CU_MEMORYTYPE_HOST 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V 2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibg h W X Y Z obCbd e f 0
122 ):
123 # Managed memory or pinned host memory
124 out.is_host_accessible = True 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzba b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbAbBbW X Y Z { mbCbd e f
125 out.is_device_accessible = True 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzba b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbAbBbW X Y Z { mbCbd e f
126 out.device_id = device_id 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzba b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbAbBbW X Y Z { mbCbd e f
127 elif memory_type == cydriver.CUmemorytype.CU_MEMORYTYPE_DEVICE: 22 g h ob0
128 out.is_host_accessible = False 22 g h ob0
129 out.is_device_accessible = True 22 g h ob0
130 out.device_id = device_id 22 g h ob0
131 else:
132 with cython.gil:
133 raise ValueError(f"Unsupported memory type: {memory_type}")
134 return 0 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
137cdef inline void _init_memory_attrs(Buffer self):
138 """Initialize memory attributes by querying the pointer."""
139 if not self._mem_attrs_inited.load(memory_order_acquire): 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
140 _query_memory_attrs(self._mem_attrs, as_cu(self._h_ptr)) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
141 self._mem_attrs_inited.store(True, memory_order_release) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnbg h dbAbBbW X Y Z { mbobCbd e f 0 KbLbMbNbObPbQbRbSbTb
144cdef class Buffer:
145 """Represent a handle to allocated memory.
147 This generic object provides a unified representation for how
148 different memory resources are to give access to their memory
149 allocations.
151 Support for data interchange mechanisms are provided by DLPack.
153 Note
154 ----
155 Pickling an IPC-enabled :class:`Buffer` embeds an
156 :class:`~_memory.IPCBufferDescriptor`. Unpickling reconstructs the buffer
157 by calling :meth:`from_ipc_descriptor` and therefore performs an IPC
158 import. Do not unpickle buffers from untrusted sources.
159 """
160 def __cinit__(self) -> None:
161 self._clear() 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPdN O P Q R S 1 9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdT U V Jbwbpeqeresete$dScue'fxbve(fwe)fbbxeyeybzb%d'd(d)d*d2 !exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~efege/d*fWd:d~cndadXdhdidjdoda b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc6d{ mb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdhe{cie/cobCbld]cMc?cmd@c[cOcPcNcQcd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 KbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9eNb8fObPbQbRbSbTb
163 def _clear(self) -> None:
164 self._h_ptr.reset() # Release the handle 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPdN O P Q R S 1 9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdT U V Jbwbpeqeresete$dScue'fxbve(fwe)fbbxeyeybzb%d'd(d)d*d2 !exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~efege/d*fWd:d~cndadXdhdidjdoda b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc6d{ mb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdhe{cie/cobCbld]cMc?cmd@c[cOcPcNcQcd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 KbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9eNb8fObPbQbRbSbTb
165 self._size = 0 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPdN O P Q R S 1 9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdT U V Jbwbpeqeresete$dScue'fxbve(fwe)fbbxeyeybzb%d'd(d)d*d2 !exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~efege/d*fWd:d~cndadXdhdidjdoda b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc6d{ mb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdhe{cie/cobCbld]cMc?cmd@c[cOcPcNcQcd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 KbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9eNb8fObPbQbRbSbTb
166 self._memory_resource = None 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPdN O P Q R S 1 9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdT U V Jbwbpeqeresete$dScue'fxbve(fwe)fbbxeyeybzb%d'd(d)d*d2 !exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~efege/d*fWd:d~cndadXdhdidjdoda b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc6d{ mb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdhe{cie/cobCbld]cMc?cmd@c[cOcPcNcQcd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 KbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9eNb8fObPbQbRbSbTb
167 self._ipc_data = None 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPdN O P Q R S 1 9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdT U V Jbwbpeqeresete$dScue'fxbve(fwe)fbbxeyeybzb%d'd(d)d*d2 !exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~efege/d*fWd:d~cndadXdhdidjdoda b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc6d{ mb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdhe{cie/cobCbld]cMc?cmd@c[cOcPcNcQcd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 KbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9eNb8fObPbQbRbSbTb
168 self._owner = None 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPdN O P Q R S 1 9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdT U V Jbwbpeqeresete$dScue'fxbve(fwe)fbbxeyeybzb%d'd(d)d*d2 !exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~efege/d*fWd:d~cndadXdhdidjdoda b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc6d{ mb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdhe{cie/cobCbld]cMc?cmd@c[cOcPcNcQcd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 KbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9eNb8fObPbQbRbSbTb
169 self._mem_attrs_inited.store(False) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPdN O P Q R S 1 9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdT U V Jbwbpeqeresete$dScue'fxbve(fwe)fbbxeyeybzb%d'd(d)d*d2 !exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~efege/d*fWd:d~cndadXdhdidjdoda b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc6d{ mb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdhe{cie/cobCbld]cMc?cmd@c[cOcPcNcQcd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 KbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9eNb8fObPbQbRbSbTb
171 def __init__(self, *args, **kwargs) -> None:
172 raise RuntimeError("Buffer objects cannot be instantiated directly. "
173 "Please use MemoryResource APIs.")
175 @classmethod
176 def _init(
177 cls, ptr: DevicePointerType, size_t size, mr: MemoryResource | None = None,
178 ipc_descriptor: IPCBufferDescriptor | None = None,
179 owner : object | None = None
180 ) -> Buffer:
181 """Create a Buffer from a raw pointer.
183 When ``mr`` is provided, the buffer takes ownership: ``mr.deallocate()``
184 is called when the buffer is closed or garbage collected. When ``owner``
185 is provided, the owner is kept alive but no deallocation is performed.
186 """
187 if mr is not None and owner is not None: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ aghe{cie/cld@c[cOcPcNcQcd e f Rc0 KbLbMbNbObPbQbRbSbTb
188 raise ValueError("owner and memory resource cannot be both specified together") 2ag
189 cdef Buffer self = Buffer.__new__(cls) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/cld@c[cOcPcNcQcd e f Rc0 KbLbMbNbObPbQbRbSbTb
190 cdef uintptr_t c_ptr = <uintptr_t>(int(ptr)) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/cld@c[cOcPcNcQcd e f Rc0 KbLbMbNbObPbQbRbSbTb
191 if mr is not None: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/cld@c[cOcPcNcQcd e f Rc0 KbLbMbNbObPbQbRbSbTb
192 self._h_ptr = deviceptr_create_with_mr(c_ptr, size, mr) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncW X VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/c@c[cOcPcNcQcd e f
193 else:
194 self._h_ptr = deviceptr_create_with_owner(c_ptr, owner) 2peqereseteScuevewebbxeye2 g h dbAbBbW X Y Z ldRc0 KbLbMbNbObPbQbRbSbTb
195 self._size = size 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/cld@c[cOcPcNcQcd e f Rc0 KbLbMbNbObPbQbRbSbTb
196 self._memory_resource = mr 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/cld@c[cOcPcNcQcd e f Rc0 KbLbMbNbObPbQbRbSbTb
197 self._ipc_data = IPCDataForBuffer(ipc_descriptor, True) if ipc_descriptor is not None else None 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/cld@c[cOcPcNcQcd e f Rc0 KbLbMbNbObPbQbRbSbTb
198 self._owner = owner 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/cld@c[cOcPcNcQcd e f Rc0 KbLbMbNbObPbQbRbSbTb
199 self._mem_attrs_inited.store(False) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/cld@c[cOcPcNcQcd e f Rc0 KbLbMbNbObPbQbRbSbTb
200 return self 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvbT U V peqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhbfegea b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc6d{ he{cie/cld@c[cOcPcNcQcd e f Rc0 KbLbMbNbObPbQbRbSbTb
202 @staticmethod
203 def _reduce_helper(mr, ipc_descriptor):
204 # The parent process's stream is not portable across processes, so the
205 # pickle path cannot thread an explicit stream through. Seed the
206 # imported buffer's deallocation with the current context's default
207 # stream; the receiver can override via buffer.close(stream).
208 return Buffer.from_ipc_descriptor(mr, ipc_descriptor, stream=default_stream())
210 def __reduce__(self) -> tuple[object, ...]:
211 # Unpickling performs a live CUDA IPC import from descriptor bytes in the
212 # pickle stream. Only deserialize Buffers from a trusted principal.
213 # Must not serialize the parent's stream!
214 return Buffer._reduce_helper, (self.memory_resource, self.ipc_descriptor) 2!exd#e$e%e'eDbUb(e)e*e+e,e-eQdRdSdTdEbVbFbGbcbjbHbIbddUdedVdebfbgbhb
216 @staticmethod
217 def from_handle(
218 ptr: DevicePointerType, size_t size, mr: MemoryResource | None = None,
219 owner: object | None = None,
220 ) -> Buffer:
221 """Create a new :class:`Buffer` object from a pointer.
223 Parameters
224 ----------
225 ptr : :obj:`~_memory.DevicePointerType`
226 Allocated buffer handle object
227 size : int
228 Memory size of the buffer
229 mr : :obj:`~_memory.MemoryResource`, optional
230 Memory resource associated with the buffer. When provided,
231 :meth:`MemoryResource.deallocate` is called when the buffer is
232 closed or garbage collected.
233 owner : object, optional
234 An object holding external allocation that the ``ptr`` points to.
235 The reference is kept as long as the buffer is alive.
236 The ``owner`` and ``mr`` cannot be specified together.
238 Note
239 ----
240 When neither ``mr`` nor ``owner`` is specified, this creates a
241 non-owning reference. The pointer will NOT be freed when the
242 :class:`Buffer` is closed or garbage collected.
243 """
244 return Buffer._init(ptr, size, mr=mr, owner=owner) 2| } ~ abpbqbrbsbtbubvbpeqereseteScuevewebbxeye2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhb^c_c`cUcJcvcTcfd|cgdibnbncg h dbAbBbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIc{ aghe{cie/cldOcPcNcQcRc0 KbLbMbNbObPbQbRbSbTb
246 @classmethod
247 def from_ipc_descriptor(
248 cls, mr: DeviceMemoryResource | PinnedMemoryResource, ipc_descriptor: IPCBufferDescriptor,
249 *, stream: Stream
250 ) -> Buffer:
251 """Import a buffer that was exported from another process.
253 Parameters
254 ----------
255 mr : :obj:`~_memory.DeviceMemoryResource` | :obj:`~_memory.PinnedMemoryResource`
256 The IPC-enabled memory resource matching the exporting process.
257 ipc_descriptor : :obj:`~_memory.IPCBufferDescriptor`
258 The descriptor exported from another process.
259 stream : :obj:`~_stream.Stream`
260 Keyword-only. The stream used for asynchronous deallocation when
261 the buffer is closed or garbage collected.
263 Note
264 ----
265 The descriptor payload and ``size`` are supplied by the exporting peer
266 and must be treated as untrusted input unless the peer is known to be
267 cooperating.
268 """
269 return _ipc.Buffer_from_ipc_descriptor(cls, mr, ipc_descriptor, stream) 2bgcgkdmd
271 @property
272 @cython.critical_section
273 def ipc_descriptor(self) -> IPCBufferDescriptor:
274 """Descriptor for sharing this buffer with other processes."""
275 if self._ipc_data is None: 2!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhbkd?cmdbdcd
276 self._ipc_data = IPCDataForBuffer(_ipc.Buffer_get_ipc_descriptor(self), False) 2!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhbkd?cmdbdcd
277 return self._ipc_data.ipc_descriptor 2!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb?cbdcd
279 def close(self, stream: Stream | GraphBuilder | None = None) -> None:
280 """Deallocate this buffer asynchronously on the given stream.
282 This buffer is released back to their memory resource
283 asynchronously on the given stream.
285 Parameters
286 ----------
287 stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`, optional
288 The stream object to use for asynchronous deallocation. If None,
289 the deallocation stream stored in the handle is used.
290 """
291 Buffer_close(self, stream) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHd7d:cMd;c=cNdOd8dPdN O P Q R S 9d!d#d| } ~ abpbqbrbsbtbubvbrdsdtdT U V Jbwb/f:f;f=f?f$dSc@f`fxb[f{f]f|fbb^f_fybzb%d'd(d)d*d2 cbjbebfbkblbgbhb/dWd:d~cndadXdhdidjdodUcJcvcg h dbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc}cLc;d=d?d@d[d]d^d_d`d{d|d}d~dkd{c/cobCbld]cMc?cmd@c[cOcPcNcQcbdcdudYdZdae0d1d2d3dbecede4dee5dvdwd
293 def __enter__(self):
294 return self 2~cndadidjdod
296 def __exit__(self, exc_type, exc_val, exc_tb):
297 self.close() 2~cndadidjdod
298 return False 2~cndadidjdod
300 def copy_to(self, dst: Buffer | None = None, *, stream: Stream | GraphBuilder) -> Buffer:
301 """Copy from this buffer to the dst buffer asynchronously on the given stream.
303 Copies the data from this buffer to the provided dst buffer.
304 If the dst buffer is not provided, then a new buffer is first
305 allocated using the associated memory resource before the copy.
307 Parameters
308 ----------
309 dst : :obj:`~_memory.Buffer`, optional
310 Destination buffer to copy data to. If not provided, a new buffer
311 is allocated using this buffer's memory resource.
312 stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
313 Keyword argument specifying the stream for the
314 asynchronous copy
316 """
317 cdef Stream s = Stream_accept(stream) 2a b c vcKcLcMcd e f
318 cdef size_t src_size = self._size 2a b c vcKcLcMcd e f
320 if dst is None: 2a b c vcKcLcMcd e f
321 if self._memory_resource is None:
322 raise ValueError("a destination buffer must be provided (this "
323 "buffer does not have a memory_resource)")
324 dst = self._memory_resource.allocate(src_size, stream=s)
326 cdef size_t dst_size = dst._size 2a b c vcKcLcMcd e f
327 if dst_size != src_size: 2a b c vcKcLcMcd e f
328 raise ValueError( "buffer sizes mismatch between src and dst (sizes "
329 f"are: src={src_size}, dst={dst_size})"
330 )
331 with nogil: 2a b c vcKcLcMcd e f
332 HANDLE_RETURN(cydriver.cuMemcpyAsync( 2a b c vcKcLcMcd e f
333 as_cu(dst._h_ptr), as_cu(self._h_ptr), src_size, as_cu(s._h_stream)))
334 return dst 2a b c vcKcLcMcd e f
336 def copy_from(self, src: Buffer, *, stream: Stream | GraphBuilder) -> None:
337 """Copy from the src buffer to this buffer asynchronously on the given stream.
339 Parameters
340 ----------
341 src : :obj:`~_memory.Buffer`
342 Source buffer to copy data from
343 stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
344 Keyword argument specifying the stream for the
345 asynchronous copy
347 """
348 cdef Stream s = Stream_accept(stream) 2| } ~ abpbqbrbsbtbubvbDbUbEbVbFbGbcbjbHbIbebfbkblbgbhb^c_c`cJc
349 cdef size_t dst_size = self._size 2| } ~ abpbqbrbsbtbubvbDbUbEbVbFbGbcbjbHbIbebfbkblbgbhb^c_c`cJc
350 cdef size_t src_size = src._size 2| } ~ abpbqbrbsbtbubvbDbUbEbVbFbGbcbjbHbIbebfbkblbgbhb^c_c`cJc
352 if src_size != dst_size: 2| } ~ abpbqbrbsbtbubvbDbUbEbVbFbGbcbjbHbIbebfbkblbgbhb^c_c`cJc
353 raise ValueError( "buffer sizes mismatch between src and dst (sizes "
354 f"are: src={src_size}, dst={dst_size})"
355 )
356 with nogil: 2| } ~ abpbqbrbsbtbubvbDbUbEbVbFbGbcbjbHbIbebfbkblbgbhb^c_c`cJc
357 HANDLE_RETURN(cydriver.cuMemcpyAsync( 2| } ~ abpbqbrbsbtbubvbDbUbEbVbFbGbcbjbHbIbebfbkblbgbhb^c_c`cJc
358 as_cu(self._h_ptr), as_cu(src._h_ptr), dst_size, as_cu(s._h_stream)))
360 def fill(self, value: int | BufferProtocol, *, stream: Stream | GraphBuilder) -> None:
361 """Fill this buffer with a repeating byte pattern.
363 Parameters
364 ----------
365 value : int | :obj:`collections.abc.Buffer`
366 - int: Must be in range [0, 256). Converted to 1 byte.
367 - :obj:`collections.abc.Buffer`: Must be 1, 2, or 4 bytes.
368 stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
369 Stream for the asynchronous fill operation.
371 Raises
372 ------
373 TypeError
374 If value is not an int and does not support the buffer protocol.
375 ValueError
376 If value byte length is not 1, 2, or 4.
377 If buffer size is not divisible by value byte length.
378 OverflowError
379 If int value is outside [0, 256).
381 """
382 cdef Stream s_stream = Stream_accept(stream) 2IdJdKd:cLd;c=c| } ~ abVcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.c
383 cdef unsigned int val
384 cdef unsigned int elem_size
385 val, elem_size = _parse_fill_value(value) 2IdJdKd:cLd;c=c| } ~ abVcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.c
387 cdef size_t buffer_size = self._size 2IdJdKd:cLd;c=c| } ~ abocwc:bxc;bpc=bqcrcsc?b@b[b]b^b_btcuc`b{byc|b}bzc~bAcWbBcXbacYbbcccdcZb0b1b2b3b4becfc5b6bCc7b8bDcgcEc9bFc!bhc#bicjckc$b%b'b(b)b*blcmc+b,bGc-b.bHc
388 cdef cydriver.CUdeviceptr dst = as_cu(self._h_ptr) 2IdJdKd:cLd;c=c| } ~ abocwc:bxc;bpc=bqcrcsc?b@b[b]b^b_btcuc`b{byc|b}bzc~bAcWbBcXbacYbbcccdcZb0b1b2b3b4becfc5b6bCc7b8bDcgcEc9bFc!bhc#bicjckc$b%b'b(b)b*blcmc+b,bGc-b.bHc
389 cdef cydriver.CUstream s = as_cu(s_stream._h_stream) 2IdJdKd:cLd;c=c| } ~ abocwc:bxc;bpc=bqcrcsc?b@b[b]b^b_btcuc`b{byc|b}bzc~bAcWbBcXbacYbbcccdcZb0b1b2b3b4becfc5b6bCc7b8bDcgcEc9bFc!bhc#bicjckc$b%b'b(b)b*blcmc+b,bGc-b.bHc
391 if elem_size == 1: 2IdJdKd:cLd;c=c| } ~ abocwc:bxc;bpc=bqcrcsc?b@b[b]b^b_btcuc`b{byc|b}bzc~bAcWbBcXbacYbbcccdcZb0b1b2b3b4becfc5b6bCc7b8bDcgcEc9bFc!bhc#bicjckc$b%b'b(b)b*blcmc+b,bGc-b.bHc
392 with nogil: 2IdJdKd:cLd;c=c| } ~ abocpcqcrcsctcuc~bacbcccdcecfcgchcicjckclcmc
393 HANDLE_RETURN(cydriver.cuMemsetD8Async(dst, val, buffer_size, s)) 2IdJdKd:cLd;c=c| } ~ abocpcqcrcsctcuc~bacbcccdcecfcgchcicjckclcmc
394 elif elem_size == 2:
395 if buffer_size & 0x1: 2wc:b?b@b[b`b{bycAcWbZb0b1b5b6bCcEc9b$b%b'b+b,bGc
396 raise ValueError(f"buffer size ({buffer_size}) must be divisible by 2") 2wcycAcCcEcGc
397 with nogil: 2:b?b@b[b`b{bWbZb0b1b5b6b9b$b%b'b+b,b
398 HANDLE_RETURN(cydriver.cuMemsetD16Async(dst, val, buffer_size // 2, s)) 2:b?b@b[b`b{bWbZb0b1b5b6b9b$b%b'b+b,b
399 elif elem_size == 4:
400 if buffer_size & 0x3: 2xc;b=b]b^b_b|b}bzcBcXbYb2b3b4b7b8bDcFc!b#b(b)b*b-b.bHc
401 raise ValueError(f"buffer size ({buffer_size}) must be divisible by 4") 2xczcBcDcFcHc
402 with nogil: 2;b=b]b^b_b|b}bXbYb2b3b4b7b8b!b#b(b)b*b-b.b
403 HANDLE_RETURN(cydriver.cuMemsetD32Async(dst, val, buffer_size // 4, s)) 2;b=b]b^b_b|b}bXbYb2b3b4b7b8b!b#b(b)b*b-b.b
405 def __dlpack__(
406 self,
407 *,
408 stream: int | None = None,
409 max_version: tuple[int, int] | None = None,
410 dl_device: tuple[int, int] | None = None,
411 copy: bool | None = None,
412 ) -> object:
413 # Note: we ignore the stream argument entirely (as if it is -1).
414 # It is the user's responsibility to maintain stream order.
415 if dl_device is not None: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` Tcnc{ mbd e f
416 raise BufferError("Sorry, not supported: dl_device other than None") 2nc
417 if copy is True: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` Tcnc{ mbd e f
418 raise BufferError("Sorry, not supported: copy=True") 2nc
419 if max_version is None: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` Tcnc{ mbd e f
420 versioned = False 2Tcnc
421 else:
422 if not isinstance(max_version, tuple) or len(max_version) != 2: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` nc{ mbd e f
423 raise BufferError(f"Expected max_version tuple[int, int], got {max_version}") 2nc
424 versioned = max_version >= (1, 0) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` nc{ mbd e f
425 return make_py_capsule(self, versioned) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` Tcnc{ mbd e f
427 def __dlpack_device__(self) -> tuple[int, int]:
428 return classify_dl_device(self) 2fd|cgdibnb{ mb
430 def __buffer__(self, flags: int, /) -> memoryview:
431 # Support for Python-level buffer protocol as per PEP 688.
432 # This raises a BufferError unless:
433 # 1. Python is 3.12+
434 # 2. This Buffer object is host accessible
435 raise NotImplementedError("WIP: Buffer.__buffer__ hasn't been implemented yet.")
437 def __release_buffer__(self, buffer: memoryview, /) -> None:
438 # Supporting method paired with __buffer__.
439 raise NotImplementedError("WIP: Buffer.__release_buffer__ hasn't been implemented yet.")
441 @property
442 def device_id(self) -> int:
443 """Return the device ordinal of this buffer."""
444 if self._memory_resource is not None: 2`e{e|e}e~e|cncg h dbAbBbW X Y Z pdqdafbfcf]cOcPcQc0 KbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9eNbObPbQbRbSbTb
445 return self._memory_resource.device_id 2`e{e|e}e~e|cncpdqdafbfcf]cOcPcQczeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e
446 _init_memory_attrs(self) 2g h dbAbBbW X Y Z 0 KbLbMbNbObPbQbRbSbTb
447 return self._mem_attrs.device_id 2g h dbAbBbW X Y Z 0 KbLbMbNbObPbQbRbSbTb
449 @property
450 def handle(self) -> int:
451 """Return the buffer handle object.
453 .. caution::
455 This handle is a Python object. To get the memory address of the underlying C
456 handle, call ``int(Buffer.handle)``.
457 """
458 # Return raw integer for compatibility with ctypes and other tools
459 # that expect a raw pointer value
460 return as_intptr(self._h_ptr) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHdIdJdKd:cLdMd;c=cFfNdOdPdN O P Q R S 1 | } ~ abpbqbrbsbtbubvb`e{e|eT U V wbydpezdqeAdreBdseteScuexbCdveDdwebbxeEdyeybzb2 DbUbEbVbFbGbcbjbHbIbebfbkblbgbhb}e~efegeWd~cadhdjda b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` UcJcvcTcncg h W X ~bWbXbacYbbcccdcZb0b1b2b3b4becfc5b6b7b8bgc9b!bhc#bicjckc$b%b'b(b)b*blcmc+b,b-b.bIcKc6d{ mbLcafbfcfMc@cNcQcd e f .eRcudvdwd0 KbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9eNb8fObPbQbRbSbTb
462 def __eq__(self, other: object) -> bool:
463 if not isinstance(other, Buffer): 2.eRcffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfef^e_e
464 return NotImplemented 2.effgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCf
465 cdef Buffer other_buf = <Buffer>other 2.eRcef^e_e
466 return (as_intptr(self._h_ptr) == as_intptr(other_buf._h_ptr) and 2.eRcef^e_e
467 self._size == other_buf._size) 2.eRc^e_e
469 def __hash__(self) -> int:
470 return hash((as_intptr(self._h_ptr), self._size)) 2RcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5f6f7f^e_e
472 def __repr__(self) -> str:
473 maybe_is_mapped = " is_mapped=True" if self.is_mapped else "" 2DbUb+d,dQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVddf
474 return f"<Buffer ptr={as_intptr(self._h_ptr):#x} size={self._size}{maybe_is_mapped}>" 2DbUb+d,dQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVddf
476 @property
477 def is_device_accessible(self) -> bool:
478 """Return True if this buffer can be accessed by the GPU, otherwise False."""
479 if self._memory_resource is not None: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` Tcfd|cgdibnbncg h dbAbBbW X Y Z Ic{ mb}c]c?cd e f 0 KbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9eNbObPbQbRbSbTb
480 return self._memory_resource.is_device_accessible 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` Tcfd|cgdibnbncIc{ mb}c]c?cd e f zeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e
481 _init_memory_attrs(self) 2g h dbAbBbW X Y Z 0 KbLbMbNbObPbQbRbSbTb
482 return self._mem_attrs.is_device_accessible 2g h dbAbBbW X Y Z 0 KbLbMbNbObPbQbRbSbTb
484 @property
485 def is_host_accessible(self) -> bool:
486 """Return True if this buffer can be accessed by the CPU, otherwise False."""
487 if self._memory_resource is not None: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` Tcfd|cgdibnbncg h dbAbBbW X Y Z oc:b;bpc=bqcrcsc?b@b[b]b^b_btcuc`b{b|b}b~bWbXbacYbbcccdcZb0b1b2b3b4becfc5b6b7b8bgc9b!bhc#bicjckc$b%b'b(b)b*blcmc+b,b-b.bIc{ mb}c]c?cd e f 0
488 return self._memory_resource.is_host_accessible 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` Tcfd|cgdibnbncoc:b;bpc=bqcrcsc?b@b[b]b^b_btcuc`b{b|b}b~bWbXbacYbbcccdcZb0b1b2b3b4becfc5b6b7b8bgc9b!bhc#bicjckc$b%b'b(b)b*blcmc+b,b-b.bIc{ mb}c]c?cd e f
489 _init_memory_attrs(self) 2g h dbAbBbW X Y Z 0
490 return self._mem_attrs.is_host_accessible 2g h dbAbBbW X Y Z 0
492 @property
493 def is_managed(self) -> bool:
494 """Return True if this buffer is CUDA managed (unified) memory, otherwise False."""
495 _init_memory_attrs(self) 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnb{ mbobCbd e f
496 if self._mem_attrs.is_managed: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V JbwbydzdAdBdjekelexbCdDdmenebboeEdybzb2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibnb{ mbobCbd e f
497 return True 2JbwbydzdAdBdjekelexbCdDdmenebboeEdybzbnb{ mb
498 # Pool-allocated managed memory does not set CU_POINTER_ATTRIBUTE_IS_MANAGED,
499 # so fall back to the memory resource when it advertises managed allocations.
500 return self._memory_resource is not None and self._memory_resource.is_managed 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V 2 a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibobCbd e f
502 @property
503 def is_mapped(self) -> bool:
504 """Return True if this buffer is mapped into the process via IPC."""
505 return getattr(self._ipc_data, "is_mapped", False) 2DbUb+d,dQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdIcdf
508 @property
509 def memory_resource(self) -> MemoryResource:
510 """Return the memory resource associated with this buffer."""
511 return self._memory_resource 2| } ~ abpbqbrbsbtbubvb!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhbUcIcKc}cLckd]cMc?cmdOcPcbdcdKbLbMbzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf5e6eEf7e8e9eNbObPbQbRbSbTb
513 @property
514 def size(self) -> int:
515 """Return the memory size of this buffer."""
516 return self._size 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 | } ~ abpbqbrbsbtbubvb`e{e|eT U V wbydpezdqeAdreBdseteScuexbCdveDdwebbxeEdyeybzb2 !exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~e~cadXdhdida b c ^c_c`c3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` TcncIcpdqdKc6d{ mb}cLcafbfcf]cMc?c@cOcPcNcQcd e f RcbdcdudYdZd0d1d2d3d4d5dvdwdzeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf5e6eEf7e8e9e
518 @property
519 def owner(self) -> object:
520 """Return the object holding external allocation."""
521 return self._owner
524cdef class MemoryResource:
525 """Abstract base class for memory resources that manage allocation and
526 deallocation of buffers.
528 Subclasses must implement methods for allocating and deallocation, as well
529 as properties associated with this memory resource from which all allocated
530 buffers will inherit. (Since all :class:`Buffer` instances allocated and
531 returned by the :meth:`allocate` method would hold a reference to self, the
532 buffer properties are retrieved simply by looking up the underlying memory
533 resource's respective property.)
534 """
536 def allocate(self, size_t size, *, stream: Stream | GraphBuilder) -> Buffer:
537 """Allocate a buffer of the requested size.
539 Parameters
540 ----------
541 size : int
542 The size of the buffer to allocate, in bytes.
543 stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
544 Keyword-only. The stream on which to perform the allocation
545 asynchronously. Must be passed explicitly; pass
546 ``device.default_stream`` to use the default stream.
548 Returns
549 -------
550 Buffer
551 The allocated buffer object, which can be used for device or host operations
552 depending on the resource's properties.
553 """
554 raise TypeError("MemoryResource.allocate must be implemented by subclasses.")
556 def deallocate(
557 self,
558 ptr: DevicePointerType,
559 size_t size,
560 *,
561 stream: Stream | GraphBuilder
562 ) -> None:
563 """Deallocate a buffer previously allocated by this resource.
565 Parameters
566 ----------
567 ptr : :obj:`~_memory.DevicePointerType`
568 The pointer or handle to the buffer to deallocate.
569 size : int
570 The size of the buffer to deallocate, in bytes.
571 stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
572 Keyword-only. The stream on which to perform the deallocation
573 asynchronously. Must be passed explicitly; pass
574 ``device.default_stream`` to use the default stream.
575 """
576 raise TypeError("MemoryResource.deallocate must be implemented by subclasses.")
578 @property
579 def is_device_accessible(self) -> bool:
580 """Whether buffers allocated by this resource are device-accessible."""
581 raise TypeError("MemoryResource.is_device_accessible must be implemented by subclasses.")
583 @property
584 def is_host_accessible(self) -> bool:
585 """Whether buffers allocated by this resource are host-accessible."""
586 raise TypeError("MemoryResource.is_host_accessible must be implemented by subclasses.")
588 @property
589 def is_managed(self) -> bool:
590 """Whether buffers allocated by this resource are CUDA managed (unified) memory."""
591 return False 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S 1 T U V a b c 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` ibobCbd e f
593 @property
594 def device_id(self) -> int:
595 """Device ID associated with this memory resource, or -1 if not applicable."""
596 raise TypeError("MemoryResource.device_id must be implemented by subclasses.")
599# Buffer Implementation Helpers
600# -----------------------------
601cdef Buffer Buffer_from_deviceptr_handle(
602 DevicePtrHandle h_ptr,
603 size_t size,
604 MemoryResource mr,
605 object ipc_descriptor = None,
606 type cls = Buffer,
607):
608 """Create a Buffer (or subclass instance) from an existing DevicePtrHandle."""
609 cdef Buffer buf = cls.__new__(cls) 2FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPd9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdJbwb$d'fxb(f)fybzb%d'd(d)d*d!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~e/d*fWd:d~cndadXdhdidjdoda b c g h pdqdKcmb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdobCb]cMc?cmdd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 zeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9e8f
610 buf._h_ptr = h_ptr 2FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPd9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdJbwb$d'fxb(f)fybzb%d'd(d)d*d!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~e/d*fWd:d~cndadXdhdidjdoda b c g h pdqdKcmb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdobCb]cMc?cmdd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 zeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9e8f
611 buf._size = size 2FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPd9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdJbwb$d'fxb(f)fybzb%d'd(d)d*d!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~e/d*fWd:d~cndadXdhdidjdoda b c g h pdqdKcmb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdobCb]cMc?cmdd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 zeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9e8f
612 buf._memory_resource = mr 2FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPd9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdJbwb$d'fxb(f)fybzb%d'd(d)d*d!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~e/d*fWd:d~cndadXdhdidjdoda b c g h pdqdKcmb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdobCb]cMc?cmdd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 zeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9e8f
613 buf._ipc_data = IPCDataForBuffer(ipc_descriptor, True) if ipc_descriptor is not None else None 2FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPd9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdJbwb$d'fxb(f)fybzb%d'd(d)d*d!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~e/d*fWd:d~cndadXdhdidjdoda b c g h pdqdKcmb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdobCb]cMc?cmdd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 zeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9e8f
614 buf._owner = None 2FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPd9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdJbwb$d'fxb(f)fybzb%d'd(d)d*d!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~e/d*fWd:d~cndadXdhdidjdoda b c g h pdqdKcmb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdobCb]cMc?cmdd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 zeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9e8f
615 buf._mem_attrs_inited.store(False) 2FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPd9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdJbwb$d'fxb(f)fybzb%d'd(d)d*d!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~e/d*fWd:d~cndadXdhdidjdoda b c g h pdqdKcmb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdobCb]cMc?cmdd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 zeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9e8f
616 return buf 2FdGdHdIdJd7d9f!fKd:cLdMd;c=cFfNdOd8dPd9d!d#d#f$f%f| } ~ abpbqbrbsbtbubvb`e{e|erdsdtdJbwb$d'fxb(f)fybzb%d'd(d)d*d!exd#e$e%e'e/e:eDbUb+d,d(e;e)e=e*e?e+e@e,e[e-e]eQdRd-d.dSdTdEbVbFbGbcbjbHbIbddUdedVdebfbkblbgbhb}e~e/d*fWd:d~cndadXdhdidjdoda b c g h pdqdKcmb}cLcafbfcf;d=d?d@d[d]d^d_d`d{d|d}d~dkdobCb]cMc?cmdd e f .eRcGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZf0f1f2f3f4f5fffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzfAfBfCfbdcddfef6f7f^e_e+f,fudYdZdae0d1d2d3dbecede4dee5dvdwd0 zeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4eDf-f.f5e6eEf7e8e9e8f
619cdef inline void Buffer_close(Buffer self, object stream):
620 """Close a buffer, freeing its memory."""
621 cdef Stream s
622 if not self._h_ptr: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHd7d:cMd;c=cNdOd8dPdN O P Q R S 9d!d#d| } ~ abpbqbrbsbtbubvbrdsdtdT U V Jbwb/f:f;f=f?f$dSc@f`fxb[f{f]f|fbb^f_fybzb%d'd(d)d*d2 cbjbebfbkblbgbhb/dWd:d~cndadXdhdidjdodUcJcvcg h dbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc}cLc;d=d?d@d[d]d^d_d`d{d|d}d~dkd{c/cobCbld]cMc?cmd@c[cOcPcNcQcbdcdudYdZdae0d1d2d3dbecede4dee5dvdwd
623 return
624 # Update deallocation stream if provided
625 if stream is not None: 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHd7d:cMd;c=cNdOd8dPdN O P Q R S 9d!d#d| } ~ abpbqbrbsbtbubvbrdsdtdT U V Jbwb/f:f;f=f?f$dSc@f`fxb[f{f]f|fbb^f_fybzb%d'd(d)d*d2 cbjbebfbkblbgbhb/dWd:d~cndadXdhdidjdodUcJcvcg h dbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc}cLc;d=d?d@d[d]d^d_d`d{d|d}d~dkd{c/cobCbld]cMc?cmd@c[cOcPcNcQcbdcdudYdZdae0d1d2d3dbecede4dee5dvdwd
626 s = Stream_accept(stream) 2rdsdtdhdKcLc/cMc[c
627 set_deallocation_stream(self._h_ptr, s._h_stream) 2rdsdtdhdKcLc/cMc[c
628 # Reset handle - RAII deleter will free the memory (and release owner ref in C++)
629 self._h_ptr.reset() 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHd7d:cMd;c=cNdOd8dPdN O P Q R S 9d!d#d| } ~ abpbqbrbsbtbubvbrdsdtdT U V Jbwb/f:f;f=f?f$dSc@f`fxb[f{f]f|fbb^f_fybzb%d'd(d)d*d2 cbjbebfbkblbgbhb/dWd:d~cndadXdhdidjdodUcJcvcg h dbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc}cLc;d=d?d@d[d]d^d_d`d{d|d}d~dkd{c/cobCbld]cMc?cmd@c[cOcPcNcQcbdcdudYdZdae0d1d2d3dbecede4dee5dvdwd
630 self._size = 0 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHd7d:cMd;c=cNdOd8dPdN O P Q R S 9d!d#d| } ~ abpbqbrbsbtbubvbrdsdtdT U V Jbwb/f:f;f=f?f$dSc@f`fxb[f{f]f|fbb^f_fybzb%d'd(d)d*d2 cbjbebfbkblbgbhb/dWd:d~cndadXdhdidjdodUcJcvcg h dbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc}cLc;d=d?d@d[d]d^d_d`d{d|d}d~dkd{c/cobCbld]cMc?cmd@c[cOcPcNcQcbdcdudYdZdae0d1d2d3dbecede4dee5dvdwd
631 self._memory_resource = None 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHd7d:cMd;c=cNdOd8dPdN O P Q R S 9d!d#d| } ~ abpbqbrbsbtbubvbrdsdtdT U V Jbwb/f:f;f=f?f$dSc@f`fxb[f{f]f|fbb^f_fybzb%d'd(d)d*d2 cbjbebfbkblbgbhb/dWd:d~cndadXdhdidjdodUcJcvcg h dbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc}cLc;d=d?d@d[d]d^d_d`d{d|d}d~dkd{c/cobCbld]cMc?cmd@c[cOcPcNcQcbdcdudYdZdae0d1d2d3dbecede4dee5dvdwd
632 self._ipc_data = None 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHd7d:cMd;c=cNdOd8dPdN O P Q R S 9d!d#d| } ~ abpbqbrbsbtbubvbrdsdtdT U V Jbwb/f:f;f=f?f$dSc@f`fxb[f{f]f|fbb^f_fybzb%d'd(d)d*d2 cbjbebfbkblbgbhb/dWd:d~cndadXdhdidjdodUcJcvcg h dbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc}cLc;d=d?d@d[d]d^d_d`d{d|d}d~dkd{c/cobCbld]cMc?cmd@c[cOcPcNcQcbdcdudYdZdae0d1d2d3dbecede4dee5dvdwd
633 self._owner = None 2i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M FdGdHd7d:cMd;c=cNdOd8dPdN O P Q R S 9d!d#d| } ~ abpbqbrbsbtbubvbrdsdtdT U V Jbwb/f:f;f=f?f$dSc@f`fxb[f{f]f|fbb^f_fybzb%d'd(d)d*d2 cbjbebfbkblbgbhb/dWd:d~cndadXdhdidjdodUcJcvcg h dbW X Y Z VcWcocwc:bXcxc;bpcYcZc0c=b1cqcrcsc?b@b[b]b^b_b2ctcuc`b{byc|b}bzc3c4c5c~bAcWb6cBcXbac7c8c9cYb!cbcccdcZb0b1b2b3b4b#cecfc5b6bCc7b8bDc$c%c'cgcEc9b(cFc!bhc)c*c+c#b,cicjckc$b%b'b(b)b*b-clcmc+b,bGc-b.bHc.cIcpdqdKc}cLc;d=d?d@d[d]d^d_d`d{d|d}d~dkd{c/cobCbld]cMc?cmd@c[cOcPcNcQcbdcdudYdZdae0d1d2d3dbecede4dee5dvdwd