Coverage for cuda/core/graph/_subclasses.pyx: 86.20%
732 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-16 01:23 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-16 01:23 +0000
1# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2#
3# SPDX-License-Identifier: Apache-2.0
5"""GraphNode subclasses — EmptyNode through SwitchNode."""
7from __future__ import annotations
9from libc.stddef cimport size_t
10from libc.stdint cimport uintptr_t
11from libc.string cimport memset as c_memset
13from cuda.bindings cimport cydriver
15from cuda.core._event cimport Event, Event_check_open
16from cuda.core._kernel_arg_handler cimport ParamHolder
17from cuda.core._launch_config cimport LaunchConfig
18from cuda.core._memory._buffer cimport Buffer
19from cuda.core._module cimport Kernel
20from cuda.core.graph._graph_definition cimport (
21 GraphCondition,
22 GraphDefinition,
23 GD_check_valid,
24)
25from cuda.core.graph._graph_node cimport (
26 GraphNode,
27 GN_check_valid,
28 _get_memcpy_memory_type,
29 _init_memcpy_params,
30 _resolve_memcpy_operand,
31)
32from cuda.core._rt cimport (
33 ContextHandle,
34 create_context_handle_ref,
35 graph_node_set_params,
36)
37from cuda.core._rt cimport (
38 EventHandle,
39 GraphExecHandle,
40 GraphHandle,
41 GraphNodeHandle,
42 KernelHandle,
43 OpaqueHandle,
44 PreparedAttachment,
45 PreparedChildGraphUpdate,
46 PreparedExecAttachment,
47 as_cu,
48 as_intptr,
49 create_child_graph_handle,
50 create_event_handle_ref,
51 create_kernel_handle_ref,
52 graph_commit_attachment,
53 graph_commit_child_graph_update,
54 graph_commit_exec_attachment,
55 graph_get_attachment,
56 graph_node_get_graph,
57 graph_prepare_attachment,
58 graph_prepare_child_graph_update,
59 graph_prepare_exec_attachment,
60 make_opaque_py,
61)
62from cuda.core._utils.cuda_utils cimport HANDLE_RETURN, _parse_fill_value
63from cuda.core._utils.version cimport cy_driver_version
65from cuda.core.graph._host_callback cimport (
66 _is_py_host_trampoline,
67 _resolve_host_callback,
68)
70from cuda.core.typing import GraphConditionalType
72__all__ = [
73 'AllocNode',
74 'ChildGraphNode',
75 'ConditionalNode',
76 'EmptyNode',
77 'EventRecordNode',
78 'EventWaitNode',
79 'ExecutableChildGraphNode',
80 'ExecutableEventRecordNode',
81 'ExecutableEventWaitNode',
82 'ExecutableGraphNode',
83 'ExecutableHostCallbackNode',
84 'ExecutableKernelNode',
85 'ExecutableMemcpyNode',
86 'ExecutableMemsetNode',
87 'FreeNode',
88 'HostCallbackNode',
89 'IfElseNode',
90 'IfNode',
91 'KernelNode',
92 'MemcpyNode',
93 'MemsetNode',
94 'SwitchNode',
95 'WhileNode',
96]
99cdef void _require_graph_node_update_support() except *:
100 cdef tuple version = cy_driver_version() 1LOUy39X+,qpohlimnY~}Nu5Z0KQMVWBCDGHIEF1;=?Rz_jkabdefgJ2Pc
101 if version < (12, 2, 0): 1LOUy39X+,qpohlimnY~}Nu5Z0KQMVWBCDGHIEF1;=?Rz_jkabdefgJ2Pc
102 raise RuntimeError(
103 "Graph node mutation requires CUDA driver 12.2 or newer; "
104 f"using driver version {'.'.join(map(str, version))}"
105 )
108cdef void _set_definition_node_params(
109 const GraphNodeHandle& h_node,
110 cydriver.CUgraphNodeParams* params,
111 OpaqueHandle owner0,
112 OpaqueHandle owner1=OpaqueHandle(),
113 cydriver.CUcontext update_ctx=NULL) except *:
114 cdef GraphHandle h_graph = graph_node_get_graph(h_node) 19X+,qpohlimnjkabdefgc
115 cdef cydriver.CUgraphNode node = as_cu(h_node) 19X+,qpohlimnjkabdefgc
116 if as_cu(h_graph) == NULL: 19X+,qpohlimnjkabdefgc
117 raise RuntimeError("GraphDefinition is no longer valid")
118 if node == NULL: 19X+,qpohlimnjkabdefgc
119 raise RuntimeError("GraphNode has been destroyed")
120 _require_graph_node_update_support() 19X+,qpohlimnjkabdefgc
121 cdef PreparedAttachment prepared
122 cdef ContextHandle h_update_ctx
123 cdef cydriver.CUresult status
124 cdef cydriver.CUresult restore_status = cydriver.CUresult.CUDA_SUCCESS 19X+,qpohlimnjkabdefgc
126 HANDLE_RETURN(graph_prepare_attachment( 19X+,qpohlimnjkabdefgc
127 h_graph, owner0, owner1, &prepared))
128 if update_ctx != NULL: 19X+,qpohlimnjkabdefgc
129 h_update_ctx = create_context_handle_ref(update_ctx) 1hlimnjkabdefgc
130 with nogil: 19X+,qpohlimnjkabdefgc
131 status = graph_node_set_params(node, params, h_update_ctx, &restore_status) 19X+,qpohlimnjkabdefgc
132 HANDLE_RETURN(status) 19X+,qpohlimnjkabdefgc
133 # The driver node now references the new owners. Publish their attachment
134 # before raising anything else: an exception here would roll back the
135 # prepared retention and leave the node pointing at released resources.
136 try: 19X+,qpohlimnjkabdefgc
137 HANDLE_RETURN(graph_commit_attachment(prepared, node)) 19X+,qpohlimnjkabdefgc
138 finally:
139 HANDLE_RETURN(restore_status) 19X+,qpohlimnjkabdefgc
142cdef void _set_executable_node_params(
143 const GraphExecHandle& h_exec,
144 const GraphNodeHandle& h_node,
145 cydriver.CUgraphNodeParams* params,
146 OpaqueHandle owner0=OpaqueHandle(),
147 OpaqueHandle owner1=OpaqueHandle()) except *:
148 _require_graph_node_update_support() 1UyYNuKQMVWBCDGHIEF1RzabJ2P
150 cdef cydriver.CUgraphExec graph_exec = as_cu(h_exec) 1UyYNuKQMVWBCDGHIEF1RzabJ2P
151 cdef cydriver.CUgraphNode node = as_cu(h_node) 1UyYNuKQMVWBCDGHIEF1RzabJ2P
152 if graph_exec == NULL: 1UyYNuKQMVWBCDGHIEF1RzabJ2P
153 raise RuntimeError("Graph has been closed")
154 if node == NULL: 1UyYNuKQMVWBCDGHIEF1RzabJ2P
155 raise RuntimeError("GraphNode has been destroyed") 1N
157 cdef PreparedExecAttachment prepared
158 HANDLE_RETURN(graph_prepare_exec_attachment( 1UyYuKQMVWBCDGHIEF1RzabJ2P
159 h_exec, owner0, owner1, &prepared))
161 cdef cydriver.CUresult status
162 with nogil: 1UyYuKQMVWBCDGHIEF1RzabJ2P
163 status = cydriver.cuGraphExecNodeSetParams( 1UyYuKQMVWBCDGHIEF1RzabJ2P
164 graph_exec, node, params)
165 if status == cydriver.CUDA_SUCCESS: 1UyYuKQMVWBCDGHIEF1RzabJ2P
166 graph_commit_exec_attachment(prepared) 1UyYuKQMVWBCDGHIEF1Rza2P
167 HANDLE_RETURN(status) 1UyYuKQMVWBCDGHIEF1RzabJ2P
170cdef bint _get_executable_node_enabled(
171 const GraphExecHandle& h_exec,
172 const GraphNodeHandle& h_node) except *:
173 _require_graph_node_update_support() 1}5Z0
175 cdef cydriver.CUgraphExec graph_exec = as_cu(h_exec) 1}5Z0
176 cdef cydriver.CUgraphNode node = as_cu(h_node) 1}5Z0
177 cdef unsigned int enabled
178 if graph_exec == NULL: 1}5Z0
179 raise RuntimeError("Graph has been closed")
180 if node == NULL: 1}5Z0
181 raise RuntimeError("GraphNode has been destroyed") 1}
182 with nogil: 15Z0
183 HANDLE_RETURN(cydriver.cuGraphNodeGetEnabled( 15Z0
184 graph_exec, node, &enabled))
185 return enabled != 0 15Z0
188cdef void _set_executable_node_enabled(
189 const GraphExecHandle& h_exec,
190 const GraphNodeHandle& h_node,
191 bint enabled) except *:
192 _require_graph_node_update_support() 1~5Z0
194 cdef cydriver.CUgraphExec graph_exec = as_cu(h_exec) 1~5Z0
195 cdef cydriver.CUgraphNode node = as_cu(h_node) 1~5Z0
196 if graph_exec == NULL: 1~5Z0
197 raise RuntimeError("Graph has been closed")
198 if node == NULL: 1~5Z0
199 raise RuntimeError("GraphNode has been destroyed") 1~
200 with nogil: 15Z0
201 HANDLE_RETURN(cydriver.cuGraphNodeSetEnabled( 15Z0
202 graph_exec, node, <unsigned int>enabled))
205cdef bint _check_node_get_params():
206 """Whether cuGraphNodeGetParams, a 13.2 driver API, is available.
208 The CUDA 13 build always has the binding. Only the driver can lack it."""
209 IF CUDA_CORE_BUILD_MAJOR >= 13:
210 return cy_driver_version() >= (13, 2, 0) 1!6#$%7'(@hlimnvwx)*rstSTjkabdef4gc
211 ELSE:
212 return False
215IF CUDA_CORE_BUILD_MAJOR >= 13:
216 cdef void _node_get_params(
217 cydriver.CUgraphNode node,
218 cydriver.CUgraphNodeParams* params) except *:
219 c_memset(params, 0, sizeof(params[0])) 1!6#$%7'(@hlimnvwx)*rstSTjkabdef4gc
220 with nogil: 1!6#$%7'(@hlimnvwx)*rstSTjkabdef4gc
221 HANDLE_RETURN(cydriver.cuGraphNodeGetParams(node, params)) 1!6#$%7'(@hlimnvwx)*rstSTjkabdef4gc
224cdef void _reject_unsupported_kernel_node(
225 cydriver.CUgraphNode node) except *:
226 cdef cydriver.CUkernelNodeAttrValue cluster
227 cdef cydriver.CUkernelNodeAttrValue cooperative
229 c_memset(&cluster, 0, sizeof(cluster)) 1qpo=?_
230 c_memset(&cooperative, 0, sizeof(cooperative)) 1qpo=?_
231 with nogil: 1qpo=?_
232 HANDLE_RETURN(cydriver.cuGraphKernelNodeGetAttribute( 1qpo=?_
233 node, <cydriver.CUkernelNodeAttrID>(
234 cydriver.CU_KERNEL_NODE_ATTRIBUTE_CLUSTER_DIMENSION),
235 &cluster))
236 HANDLE_RETURN(cydriver.cuGraphKernelNodeGetAttribute( 1qpo=?_
237 node, <cydriver.CUkernelNodeAttrID>(
238 cydriver.CU_KERNEL_NODE_ATTRIBUTE_COOPERATIVE),
239 &cooperative))
240 if (cluster.clusterDim.x != 0 or cluster.clusterDim.y != 0 or 1qpo=?_
241 cluster.clusterDim.z != 0 or cooperative.cooperative != 0): 1qpo=?_
242 raise NotImplementedError( 1_
243 "updating clustered or cooperative kernel nodes is not supported")
246cdef inline bint _is_linear_memcpy_memory_type(
247 cydriver.CUmemorytype memory_type) noexcept nogil:
248 # HOST and DEVICE name the location of a linear operand. UNIFIED is what
249 # the driver records for a copy captured from cuMemcpyAsync: a generic
250 # address that it resolves itself, stored in the device-pointer field.
251 return (memory_type == cydriver.CU_MEMORYTYPE_HOST 1hlivwxrstjk4c
252 or memory_type == cydriver.CU_MEMORYTYPE_DEVICE 1hlivwxrstjkabdef4c
253 or memory_type == cydriver.CU_MEMORYTYPE_UNIFIED) 1hlivwxrstjkabdef4c
256cdef str _memcpy_memory_type_tag(cydriver.CUmemorytype memory_type):
257 if memory_type == cydriver.CU_MEMORYTYPE_HOST: 2f 1e
258 return "H"
259 if memory_type == cydriver.CU_MEMORYTYPE_DEVICE: 2f 1e
260 return "D" 21e
261 if memory_type == cydriver.CU_MEMORYTYPE_UNIFIED: 1f
262 return "U" 1f
263 if memory_type == cydriver.CU_MEMORYTYPE_ARRAY:
264 return "A"
265 return str(int(memory_type))
268cdef bint _is_supported_memcpy_descriptor(
269 cydriver.CUDA_MEMCPY3D* params) noexcept nogil:
270 return (
271 _is_linear_memcpy_memory_type(params.srcMemoryType) 1hlivwxrstjkabdef4c
272 and _is_linear_memcpy_memory_type(params.dstMemoryType) 1hlivwxrstjkabdef4c
273 and params.srcXInBytes == 0 1hlivwxrstjkabdef4c
274 and params.srcY == 0 1hlivwxrstjkabdefc
275 and params.srcZ == 0 1hlivwxrstjkabdefc
276 and params.srcLOD == 0 1hlivwxrstjkabdefc
277 and params.srcPitch == 0 1hlivwxrstjkabdefc
278 and params.srcHeight == 0 1hlivwxrstjkabdefc
279 and params.dstXInBytes == 0 1hlivwxrstjkabdefc
280 and params.dstY == 0 1hlivwxrstjkabdefc
281 and params.dstZ == 0 1hlivwxrstjkabdefc
282 and params.dstLOD == 0 1hlivwxrstjkabdefc
283 and params.dstPitch == 0 1hlivwxrstjkabdefc
284 and params.dstHeight == 0 1hlivwxrstjkabdefc
285 and params.Height == 1 1hlivwxrstjkabdefc
286 and params.Depth == 1 1hlivwxrstjkabdefc
287 and params.reserved0 == NULL 1hlivwxrstjkabdefc
288 and params.reserved1 == NULL 1hlivwxrstjkabdefc
289 )
292cdef class EmptyNode(GraphNode):
293 """An empty (synchronization) node."""
295 @staticmethod
296 cdef EmptyNode _create_impl(GraphNodeHandle h_node):
297 cdef EmptyNode n = EmptyNode.__new__(EmptyNode) 2;f=f^c_c?f- . / : `c{c|c@f[f]f}csb~cabtbadbdcdddedubfdqbvbgd^fwbhdxbidjdkdld_fmdnd`fod{f|f8 WdXdYdZd0d}fZf~fagbg1dcgdgegLbR 8d9dpdyb0fqdzbrdAbA sdBbtdCbudDbvdEbwdFbxdGbydHbzdIb
298 n._h_node = h_node 2;f=f^c_c?f- . / : `c{c|c@f[f]f}csb~cabtbadbdcdddedubfdqbvbgd^fwbhdxbidjdkdld_fmdnd`fod{f|f8 WdXdYdZd0d}fZf~fagbg1dcgdgegLbR 8d9dpdyb0fqdzbrdAbA sdBbtdCbudDbvdEbwdFbxdGbydHbzdIb
299 return n 2;f=f^c_c?f- . / : `c{c|c@f[f]f}csb~cabtbadbdcdddedubfdqbvbgd^fwbhdxbidjdkdld_fmdnd`fod{f|f8 WdXdYdZd0d}fZf~fagbg1dcgdgegLbR 8d9dpdyb0fqdzbrdAbA sdBbtdCbudDbvdEbwdFbxdGbydHbzdIb
301 def __repr__(self) -> str:
302 return f"<EmptyNode handle=0x{as_intptr(self._h_node):x}>" 2Zf0frg
305cdef class KernelNode(GraphNode):
306 """A kernel launch node.
308 Properties
309 ----------
310 grid : tuple of int
311 Grid dimensions (gridDimX, gridDimY, gridDimZ).
312 block : tuple of int
313 Block dimensions (blockDimX, blockDimY, blockDimZ).
314 shmem_size : int
315 Dynamic shared memory size in bytes.
316 kernel : Kernel
317 The kernel object for this launch node.
318 config : LaunchConfig
319 A LaunchConfig reconstructed from this node's parameters.
320 """
322 @staticmethod
323 cdef KernelNode _create_with_params(GraphNodeHandle h_node,
324 tuple grid, tuple block, unsigned int shmem_size,
325 KernelHandle h_kernel):
326 """Create from known params (called by launch() builder)."""
327 cdef KernelNode n = KernelNode.__new__(KernelNode) 2Dc2eEcFcGcAd3e4e5e6e7e8e9etcBducCdvcDdwcEdxcFdycGdzc!eAcqcBcCcMb#e$e+d(c%e'e` WdXdYdZd0d[ y q p o McNcOc,d-d.d~ } N JbKb5 TbB C D Lb= rc? z _ scJ (eHd)eId*eJd+eA Kd,eLd-eMd.eNd/eOd:ePd;eQd=eRd?e
328 n._h_node = h_node 2Dc2eEcFcGcAd3e4e5e6e7e8e9etcBducCdvcDdwcEdxcFdycGdzc!eAcqcBcCcMb#e$e+d(c%e'e` WdXdYdZd0d[ y q p o McNcOc,d-d.d~ } N JbKb5 TbB C D Lb= rc? z _ scJ (eHd)eId*eJd+eA Kd,eLd-eMd.eNd/eOd:ePd;eQd=eRd?e
329 n._grid = grid 2Dc2eEcFcGcAd3e4e5e6e7e8e9etcBducCdvcDdwcEdxcFdycGdzc!eAcqcBcCcMb#e$e+d(c%e'e` WdXdYdZd0d[ y q p o McNcOc,d-d.d~ } N JbKb5 TbB C D Lb= rc? z _ scJ (eHd)eId*eJd+eA Kd,eLd-eMd.eNd/eOd:ePd;eQd=eRd?e
330 n._block = block 2Dc2eEcFcGcAd3e4e5e6e7e8e9etcBducCdvcDdwcEdxcFdycGdzc!eAcqcBcCcMb#e$e+d(c%e'e` WdXdYdZd0d[ y q p o McNcOc,d-d.d~ } N JbKb5 TbB C D Lb= rc? z _ scJ (eHd)eId*eJd+eA Kd,eLd-eMd.eNd/eOd:ePd;eQd=eRd?e
331 n._shmem_size = shmem_size 2Dc2eEcFcGcAd3e4e5e6e7e8e9etcBducCdvcDdwcEdxcFdycGdzc!eAcqcBcCcMb#e$e+d(c%e'e` WdXdYdZd0d[ y q p o McNcOc,d-d.d~ } N JbKb5 TbB C D Lb= rc? z _ scJ (eHd)eId*eJd+eA Kd,eLd-eMd.eNd/eOd:ePd;eQd=eRd?e
332 n._h_kernel = h_kernel 2Dc2eEcFcGcAd3e4e5e6e7e8e9etcBducCdvcDdwcEdxcFdycGdzc!eAcqcBcCcMb#e$e+d(c%e'e` WdXdYdZd0d[ y q p o McNcOc,d-d.d~ } N JbKb5 TbB C D Lb= rc? z _ scJ (eHd)eId*eJd+eA Kd,eLd-eMd.eNd/eOd:ePd;eQd=eRd?e
333 return n 2Dc2eEcFcGcAd3e4e5e6e7e8e9etcBducCdvcDdwcEdxcFdycGdzc!eAcqcBcCcMb#e$e+d(c%e'e` WdXdYdZd0d[ y q p o McNcOc,d-d.d~ } N JbKb5 TbB C D Lb= rc? z _ scJ (eHd)eId*eJd+eA Kd,eLd-eMd.eNd/eOd:ePd;eQd=eRd?e
335 @staticmethod
336 cdef KernelNode _create_from_driver(GraphNodeHandle h_node):
337 """Create by fetching params from the driver (called by _create factory)."""
338 cdef cydriver.CUgraphNode node = as_cu(h_node) 2DcEcFcGctcAcqcBcCcMb` [
339 cdef cydriver.CUDA_KERNEL_NODE_PARAMS params
340 with nogil: 2DcEcFcGctcAcqcBcCcMb` [
341 HANDLE_RETURN(cydriver.cuGraphKernelNodeGetParams(node, ¶ms)) 2DcEcFcGctcAcqcBcCcMb` [
342 cdef KernelHandle h_kernel = create_kernel_handle_ref(params.kern) 2DcEcFcGctcAcqcBcCcMb` [
343 return KernelNode._create_with_params( 2DcEcFcGctcAcqcBcCcMb` [
344 h_node,
345 (params.gridDimX, params.gridDimY, params.gridDimZ), 2DcEcFcGctcAcqcBcCcMb` [
346 (params.blockDimX, params.blockDimY, params.blockDimZ), 2DcEcFcGctcAcqcBcCcMb` [
347 params.sharedMemBytes,
348 h_kernel)
350 def __repr__(self) -> str:
351 return (f"<KernelNode handle=0x{as_intptr(self._h_node):x}" 2y z gg
352 f" kernel=0x{as_intptr(self._h_kernel):x}>") 2y z gg
354 def update(
355 self,
356 *,
357 config: LaunchConfig | None = None,
358 kernel: Kernel | None = None,
359 args=None,
360 ) -> None:
361 """Replace selected kernel launch parameters.
363 Omitted parameters preserve their current values. Changing ``kernel``
364 requires ``args``, including ``args=()`` for a no-argument kernel.
365 Clustered and cooperative kernel nodes are not supported.
367 .. warning::
369 Use caution when a retained kernel argument directly or indirectly
370 owns a graph. Any reference cycle involving the argument and a
371 graph that retains it cannot be broken by Python's cyclic garbage
372 collector. Use a weak reference to break such cycles.
373 """
374 GN_check_valid(self) 2q p o McNcOc,d-d.d= rc? _ sc
375 cdef LaunchConfig c_config
376 cdef Kernel c_kernel
377 cdef ParamHolder arg_holder
378 cdef object kernel_args
379 cdef KernelHandle h_kernel = self._h_kernel 2q p o McNcOc= rc? _ sc
380 cdef OpaqueHandle kernel_owner
381 cdef OpaqueHandle args_owner
382 cdef GraphHandle h_graph = graph_node_get_graph(self._h_node) 2q p o McNcOc= rc? _ sc
383 cdef cydriver.CUgraphNode node = as_cu(self._h_node) 2q p o McNcOc= rc? _ sc
384 cdef cydriver.CUgraphNodeParams params
386 if config is not None: 2q p o McNcOc= rc? _ sc
387 c_config = config 2p McNcOcrc_ sc
388 if (c_config.cluster is not None or 2p _ sc
389 c_config.is_cooperative): 2p _ sc
390 raise NotImplementedError( 2sc
391 "updating clustered or cooperative kernel nodes is not "
392 "supported")
393 _require_graph_node_update_support() 1qpo=?_
394 _reject_unsupported_kernel_node(node) 1qpo=?_
395 if kernel is not None: 1qpo=?
396 if args is None: 1o?
397 raise ValueError("changing kernel requires args") 1?
398 c_kernel = kernel 1o
399 h_kernel = c_kernel._h_kernel 1o
400 if args is not None: 1qpo=
401 arg_holder = ParamHolder(args) 1qo=
403 c_memset(¶ms, 0, sizeof(params)) 1qpo
404 params.type = cydriver.CU_GRAPH_NODE_TYPE_KERNEL 1qpo
405 with nogil: 1qpo
406 HANDLE_RETURN(cydriver.cuGraphKernelNodeGetParams( 1qpo
407 node, <cydriver.CUDA_KERNEL_NODE_PARAMS*>¶ms.kernel))
408 HANDLE_RETURN(graph_get_attachment( 1qpo
409 h_graph, node, &kernel_owner, &args_owner))
411 if config is not None: 1qpo
412 params.kernel.gridDimX = c_config.grid[0] 1p
413 params.kernel.gridDimY = c_config.grid[1] 1p
414 params.kernel.gridDimZ = c_config.grid[2] 1p
415 params.kernel.blockDimX = c_config.block[0] 1p
416 params.kernel.blockDimY = c_config.block[1] 1p
417 params.kernel.blockDimZ = c_config.block[2] 1p
418 params.kernel.sharedMemBytes = c_config.shmem_size 1p
419 if kernel is not None: 1qpo
420 params.kernel.kern = as_cu(h_kernel) 1o
421 params.kernel.func = <cydriver.CUfunction>NULL 1o
422 params.kernel.ctx = <cydriver.CUcontext>NULL 1o
423 kernel_owner = h_kernel 1o
424 if args is not None: 1qpo
425 params.kernel.kernelParams = <void**><uintptr_t>arg_holder.ptr 1qo
426 params.kernel.extra = NULL 1qo
427 kernel_args = arg_holder.kernel_args 1qo
428 if kernel_args is None: 1qo
429 args_owner = OpaqueHandle() 1o
430 else:
431 args_owner = make_opaque_py(kernel_args) 1q
433 _set_definition_node_params( 1qpo
434 self._h_node, ¶ms, kernel_owner, args_owner)
435 self._grid = ( 1qpo
436 params.kernel.gridDimX, 1qpo
437 params.kernel.gridDimY, 1qpo
438 params.kernel.gridDimZ, 1qpo
439 )
440 self._block = ( 1qpo
441 params.kernel.blockDimX, 1qpo
442 params.kernel.blockDimY, 1qpo
443 params.kernel.blockDimZ, 1qpo
444 )
445 self._shmem_size = params.kernel.sharedMemBytes 1qpo
446 self._h_kernel = h_kernel 1qpo
448 @property
449 def grid(self) -> tuple[int, int, int]:
450 """Grid dimensions as a 3-tuple (gridDimX, gridDimY, gridDimZ)."""
451 return self._grid 2_ebb
453 @property
454 def block(self) -> tuple[int, int, int]:
455 """Block dimensions as a 3-tuple (blockDimX, blockDimY, blockDimZ)."""
456 return self._block 2_ebb
458 @property
459 def shmem_size(self) -> int:
460 """Dynamic shared memory size in bytes."""
461 return self._shmem_size 2_ebb
463 @property
464 def kernel(self) -> Kernel:
465 """The Kernel object for this launch node."""
466 return Kernel._from_handle(self._h_kernel) 2_ebb+d(cq p o B C D = rc?
468 @property
469 def config(self) -> LaunchConfig:
470 """A LaunchConfig reconstructed from this node's grid, block, and shmem_size.
472 Note: cluster dimensions and is_cooperative are not preserved
473 by the CUDA driver's kernel node params, so they are not included.
474 """
475 return LaunchConfig(grid=self._grid, block=self._block, 2_ebbq p o B C D = rc?
476 shmem_size=self._shmem_size) 2_ebbq p o B C D = rc?
479cdef class AllocNode(GraphNode):
480 """A memory allocation node.
482 Properties
483 ----------
484 dptr : int
485 The device pointer for the allocation.
486 bytesize : int
487 The number of bytes allocated.
488 device_id : int
489 The device on which the allocation was made.
490 memory_type : GraphMemoryType | str
491 The type of memory allocated.
492 peer_access : tuple of int
493 Device IDs that have read-write access to this allocation.
494 """
496 @staticmethod
497 cdef AllocNode _create_with_params(GraphNodeHandle h_node,
498 cydriver.CUdeviceptr dptr, size_t bytesize,
499 int device_id, str memory_type, tuple peer_access):
500 """Create from known params (called by allocate() builder)."""
501 cdef AllocNode n = AllocNode.__new__(AllocNode) 2!d#dPc/d:d;d=d^c?d_c@d[dQcRcScTcUc- . / : lbmbnbob]d^d_d`c{c|c`d{d}c)c*cVcucsbUbVbWbXbjb|dkb}d~cNb+cOb,cPbWcbbvcabtbcbYbdbZbeb0bfb1b~dadaebdbecedecdeeddfegeheieed-c.cXcwcub2b3b4b5b6bje7bke8bfd9b/c!b:c#bYc$bxcqbvb%b'b(b)b*b+b,b-b.ble/bme:bgd;b;c=b=c?bZc@bycwb[b]b^b_b`b{b|b}bneoehd?c@c0czcxb~bacbcccpeidqejdresetekdueldvewexemdyendzeAeod$dBe1c2cgbhbpb8 HcCepd3cybdcDeqd4czbecEerd5cAbfcA Fesd6cBbgcGetd7cCbhcHeud8cDbicIevd9cEbjcJewd!cFbkcKexd#cGblcLeyd$cHbmcMezd%cIbnc
502 n._h_node = h_node 2!d#dPc/d:d;d=d^c?d_c@d[dQcRcScTcUc- . / : lbmbnbob]d^d_d`c{c|c`d{d}c)c*cVcucsbUbVbWbXbjb|dkb}d~cNb+cOb,cPbWcbbvcabtbcbYbdbZbeb0bfb1b~dadaebdbecedecdeeddfegeheieed-c.cXcwcub2b3b4b5b6bje7bke8bfd9b/c!b:c#bYc$bxcqbvb%b'b(b)b*b+b,b-b.ble/bme:bgd;b;c=b=c?bZc@bycwb[b]b^b_b`b{b|b}bneoehd?c@c0czcxb~bacbcccpeidqejdresetekdueldvewexemdyendzeAeod$dBe1c2cgbhbpb8 HcCepd3cybdcDeqd4czbecEerd5cAbfcA Fesd6cBbgcGetd7cCbhcHeud8cDbicIevd9cEbjcJewd!cFbkcKexd#cGblcLeyd$cHbmcMezd%cIbnc
503 n._dptr = dptr 2!d#dPc/d:d;d=d^c?d_c@d[dQcRcScTcUc- . / : lbmbnbob]d^d_d`c{c|c`d{d}c)c*cVcucsbUbVbWbXbjb|dkb}d~cNb+cOb,cPbWcbbvcabtbcbYbdbZbeb0bfb1b~dadaebdbecedecdeeddfegeheieed-c.cXcwcub2b3b4b5b6bje7bke8bfd9b/c!b:c#bYc$bxcqbvb%b'b(b)b*b+b,b-b.ble/bme:bgd;b;c=b=c?bZc@bycwb[b]b^b_b`b{b|b}bneoehd?c@c0czcxb~bacbcccpeidqejdresetekdueldvewexemdyendzeAeod$dBe1c2cgbhbpb8 HcCepd3cybdcDeqd4czbecEerd5cAbfcA Fesd6cBbgcGetd7cCbhcHeud8cDbicIevd9cEbjcJewd!cFbkcKexd#cGblcLeyd$cHbmcMezd%cIbnc
504 n._bytesize = bytesize 2!d#dPc/d:d;d=d^c?d_c@d[dQcRcScTcUc- . / : lbmbnbob]d^d_d`c{c|c`d{d}c)c*cVcucsbUbVbWbXbjb|dkb}d~cNb+cOb,cPbWcbbvcabtbcbYbdbZbeb0bfb1b~dadaebdbecedecdeeddfegeheieed-c.cXcwcub2b3b4b5b6bje7bke8bfd9b/c!b:c#bYc$bxcqbvb%b'b(b)b*b+b,b-b.ble/bme:bgd;b;c=b=c?bZc@bycwb[b]b^b_b`b{b|b}bneoehd?c@c0czcxb~bacbcccpeidqejdresetekdueldvewexemdyendzeAeod$dBe1c2cgbhbpb8 HcCepd3cybdcDeqd4czbecEerd5cAbfcA Fesd6cBbgcGetd7cCbhcHeud8cDbicIevd9cEbjcJewd!cFbkcKexd#cGblcLeyd$cHbmcMezd%cIbnc
505 n._device_id = device_id 2!d#dPc/d:d;d=d^c?d_c@d[dQcRcScTcUc- . / : lbmbnbob]d^d_d`c{c|c`d{d}c)c*cVcucsbUbVbWbXbjb|dkb}d~cNb+cOb,cPbWcbbvcabtbcbYbdbZbeb0bfb1b~dadaebdbecedecdeeddfegeheieed-c.cXcwcub2b3b4b5b6bje7bke8bfd9b/c!b:c#bYc$bxcqbvb%b'b(b)b*b+b,b-b.ble/bme:bgd;b;c=b=c?bZc@bycwb[b]b^b_b`b{b|b}bneoehd?c@c0czcxb~bacbcccpeidqejdresetekdueldvewexemdyendzeAeod$dBe1c2cgbhbpb8 HcCepd3cybdcDeqd4czbecEerd5cAbfcA Fesd6cBbgcGetd7cCbhcHeud8cDbicIevd9cEbjcJewd!cFbkcKexd#cGblcLeyd$cHbmcMezd%cIbnc
506 n._memory_type = memory_type 2!d#dPc/d:d;d=d^c?d_c@d[dQcRcScTcUc- . / : lbmbnbob]d^d_d`c{c|c`d{d}c)c*cVcucsbUbVbWbXbjb|dkb}d~cNb+cOb,cPbWcbbvcabtbcbYbdbZbeb0bfb1b~dadaebdbecedecdeeddfegeheieed-c.cXcwcub2b3b4b5b6bje7bke8bfd9b/c!b:c#bYc$bxcqbvb%b'b(b)b*b+b,b-b.ble/bme:bgd;b;c=b=c?bZc@bycwb[b]b^b_b`b{b|b}bneoehd?c@c0czcxb~bacbcccpeidqejdresetekdueldvewexemdyendzeAeod$dBe1c2cgbhbpb8 HcCepd3cybdcDeqd4czbecEerd5cAbfcA Fesd6cBbgcGetd7cCbhcHeud8cDbicIevd9cEbjcJewd!cFbkcKexd#cGblcLeyd$cHbmcMezd%cIbnc
507 n._peer_access = peer_access 2!d#dPc/d:d;d=d^c?d_c@d[dQcRcScTcUc- . / : lbmbnbob]d^d_d`c{c|c`d{d}c)c*cVcucsbUbVbWbXbjb|dkb}d~cNb+cOb,cPbWcbbvcabtbcbYbdbZbeb0bfb1b~dadaebdbecedecdeeddfegeheieed-c.cXcwcub2b3b4b5b6bje7bke8bfd9b/c!b:c#bYc$bxcqbvb%b'b(b)b*b+b,b-b.ble/bme:bgd;b;c=b=c?bZc@bycwb[b]b^b_b`b{b|b}bneoehd?c@c0czcxb~bacbcccpeidqejdresetekdueldvewexemdyendzeAeod$dBe1c2cgbhbpb8 HcCepd3cybdcDeqd4czbecEerd5cAbfcA Fesd6cBbgcGetd7cCbhcHeud8cDbicIevd9cEbjcJewd!cFbkcKexd#cGblcLeyd$cHbmcMezd%cIbnc
508 return n 2!d#dPc/d:d;d=d^c?d_c@d[dQcRcScTcUc- . / : lbmbnbob]d^d_d`c{c|c`d{d}c)c*cVcucsbUbVbWbXbjb|dkb}d~cNb+cOb,cPbWcbbvcabtbcbYbdbZbeb0bfb1b~dadaebdbecedecdeeddfegeheieed-c.cXcwcub2b3b4b5b6bje7bke8bfd9b/c!b:c#bYc$bxcqbvb%b'b(b)b*b+b,b-b.ble/bme:bgd;b;c=b=c?bZc@bycwb[b]b^b_b`b{b|b}bneoehd?c@c0czcxb~bacbcccpeidqejdresetekdueldvewexemdyendzeAeod$dBe1c2cgbhbpb8 HcCepd3cybdcDeqd4czbecEerd5cAbfcA Fesd6cBbgcGetd7cCbhcHeud8cDbicIevd9cEbjcJewd!cFbkcKexd#cGblcLeyd$cHbmcMezd%cIbnc
510 @staticmethod
511 cdef AllocNode _create_from_driver(GraphNodeHandle h_node):
512 """Create by fetching params from the driver (called by _create factory)."""
513 cdef cydriver.CUgraphNode node = as_cu(h_node) 2jbkbNbObPbbbabcbdbebfb6b7b8b9b!b#b$bqb%b(b*b,b.b/b:b;b=b?b@b[b^b`b|bgbhb
514 cdef cydriver.CUDA_MEM_ALLOC_NODE_PARAMS params
515 with nogil: 2jbkbNbObPbbbabcbdbebfb6b7b8b9b!b#b$bqb%b(b*b,b.b/b:b;b=b?b@b[b^b`b|bgbhb
516 HANDLE_RETURN(cydriver.cuGraphMemAllocNodeGetParams(node, ¶ms)) 2jbkbNbObPbbbabcbdbebfb6b7b8b9b!b#b$bqb%b(b*b,b.b/b:b;b=b?b@b[b^b`b|bgbhb
518 cdef str memory_type
519 if params.poolProps.allocType == cydriver.CUmemAllocationType.CU_MEM_ALLOCATION_TYPE_PINNED: 2jbkbNbObPbbbabcbdbebfb6b7b8b9b!b#b$bqb%b(b*b,b.b/b:b;b=b?b@b[b^b`b|bgbhb
520 if params.poolProps.location.type == cydriver.CUmemLocationType.CU_MEM_LOCATION_TYPE_HOST: 2jbkbNbObPbbbabcbdbebfb6b7b8b9b!b#b$bqb%b(b*b,b.b/b:b;b=b?b@b[b^b`b|bhb
521 memory_type = "host"
522 else:
523 memory_type = "device" 2jbkbNbObPbbbabcbdbebfb6b7b8b9b!b#b$bqb%b(b*b,b.b/b:b;b=b?b@b[b^b`b|bhb
524 else:
525 IF CUDA_CORE_BUILD_MAJOR >= 13:
526 if params.poolProps.allocType == cydriver.CUmemAllocationType.CU_MEM_ALLOCATION_TYPE_MANAGED: 2gb
527 memory_type = "managed" 2gb
528 else:
529 memory_type = "device"
530 ELSE:
531 memory_type = "device"
533 cdef list peer_ids = [] 2jbkbNbObPbbbabcbdbebfb6b7b8b9b!b#b$bqb%b(b*b,b.b/b:b;b=b?b@b[b^b`b|bgbhb
534 cdef size_t i
535 for i in range(params.accessDescCount): 2jbkbNbObPbbbabcbdbebfb6b7b8b9b!b#b$bqb%b(b*b,b.b/b:b;b=b?b@b[b^b`b|bgbhb
536 peer_ids.append(<int>params.accessDescs[i].location.id) 2hb
538 return AllocNode._create_with_params( 2jbkbNbObPbbbabcbdbebfb6b7b8b9b!b#b$bqb%b(b*b,b.b/b:b;b=b?b@b[b^b`b|bgbhb
539 h_node, params.dptr, params.bytesize,
540 <int>params.poolProps.location.id, memory_type, tuple(peer_ids)) 2jbkbNbObPbbbabcbdbebfb6b7b8b9b!b#b$bqb%b(b*b,b.b/b:b;b=b?b@b[b^b`b|bgbhb
542 def __repr__(self) -> str:
543 return (f"<AllocNode handle=0x{as_intptr(self._h_node):x}" 2hg
544 f" dptr=0x{self._dptr:x} size={self._bytesize}>") 2hg
546 @property
547 def dptr(self) -> int:
548 """The device pointer for the allocation."""
549 return self._dptr 2!d#dPcQcRcScTcUc- . / : lbmbnbobRfSfVcsbUbVbWbXbjbkbWctbYbZb0b1bXcub2b3b4b5bYcvb'b)b+b-bZcwb]b_b{b}b0cxb~bacbccc$dgbpb8 3cybdc4czbec5cAbfcA 6cBbgc7cCbhc8cDbic9cEbjc!cFbkc#cGblc$cHbmc%cIbnc
551 @property
552 def bytesize(self) -> int:
553 """The number of bytes allocated."""
554 return self._bytesize 2RfSfjbkb
556 @property
557 def device_id(self) -> int:
558 """The device on which the allocation was made."""
559 return self._device_id 2RfSfjbkb
561 @property
562 def memory_type(self) -> str:
563 """The type of memory: ``"device"``, ``"host"``, or ``"managed"``."""
564 return self._memory_type 2RfSfjbkbgb
566 @property
567 def peer_access(self) -> tuple[int, ...]:
568 """Device IDs with read-write access to this allocation."""
569 return self._peer_access 2RfSfjbkbhb
572cdef class FreeNode(GraphNode):
573 """A memory deallocation node.
575 Properties
576 ----------
577 dptr : int
578 The device pointer being freed.
579 """
581 @staticmethod
582 cdef FreeNode _create_with_params(GraphNodeHandle h_node,
583 cydriver.CUdeviceptr dptr):
584 """Create from known params (called by deallocate() builder)."""
585 cdef FreeNode n = FreeNode.__new__(FreeNode) 2PcQcRcScTcUc- . / : lbmbnbobVcWcXcYcZc0cpb3c4c5cA 6c7c8c9c!c#c$c%c
586 n._h_node = h_node 2PcQcRcScTcUc- . / : lbmbnbobVcWcXcYcZc0cpb3c4c5cA 6c7c8c9c!c#c$c%c
587 n._dptr = dptr 2PcQcRcScTcUc- . / : lbmbnbobVcWcXcYcZc0cpb3c4c5cA 6c7c8c9c!c#c$c%c
588 return n 2PcQcRcScTcUc- . / : lbmbnbobVcWcXcYcZc0cpb3c4c5cA 6c7c8c9c!c#c$c%c
590 @staticmethod
591 cdef FreeNode _create_from_driver(GraphNodeHandle h_node):
592 """Create by fetching params from the driver (called by _create factory)."""
593 cdef cydriver.CUgraphNode node = as_cu(h_node) 2pb
594 cdef cydriver.CUdeviceptr dptr
595 with nogil: 2pb
596 HANDLE_RETURN(cydriver.cuGraphMemFreeNodeGetParams(node, &dptr)) 2pb
597 return FreeNode._create_with_params(h_node, dptr) 2pb
599 def __repr__(self) -> str:
600 return f"<FreeNode handle=0x{as_intptr(self._h_node):x} dptr=0x{self._dptr:x}>" 2sg
602 @property
603 def dptr(self) -> int:
604 """The device pointer being freed."""
605 return self._dptr 2tgPbpb
608cdef class MemsetNode(GraphNode):
609 """A memset node.
611 Properties
612 ----------
613 dptr : int
614 The destination device pointer.
615 value : int
616 The fill value.
617 element_size : int
618 Element size in bytes (1, 2, or 4).
619 width : int
620 Width of the row in elements.
621 height : int
622 Number of rows.
623 pitch : int
624 Pitch in bytes (unused if height is 1).
625 """
627 @staticmethod
628 cdef MemsetNode _create_with_params(GraphNodeHandle h_node,
629 cydriver.CUdeviceptr dptr, unsigned int value,
630 unsigned int element_size, size_t width,
631 size_t height, size_t pitch):
632 """Create from known params (called by memset() builder)."""
633 cdef MemsetNode n = MemsetNode.__new__(MemsetNode) 2- . / : lbmbnbobUbVbWbXbYbZb0b1b2b3b4b5b'b)b+b-b]b_b{b}b~bacbccc%d'd(d[ [cm n ) * 2d3d0 E F S T g occ dcecfcA gchcicjckclcmcnc
634 n._h_node = h_node 2- . / : lbmbnbobUbVbWbXbYbZb0b1b2b3b4b5b'b)b+b-b]b_b{b}b~bacbccc%d'd(d[ [cm n ) * 2d3d0 E F S T g occ dcecfcA gchcicjckclcmcnc
635 n._dptr = dptr 2- . / : lbmbnbobUbVbWbXbYbZb0b1b2b3b4b5b'b)b+b-b]b_b{b}b~bacbccc%d'd(d[ [cm n ) * 2d3d0 E F S T g occ dcecfcA gchcicjckclcmcnc
636 n._value = value 2- . / : lbmbnbobUbVbWbXbYbZb0b1b2b3b4b5b'b)b+b-b]b_b{b}b~bacbccc%d'd(d[ [cm n ) * 2d3d0 E F S T g occ dcecfcA gchcicjckclcmcnc
637 n._element_size = element_size 2- . / : lbmbnbobUbVbWbXbYbZb0b1b2b3b4b5b'b)b+b-b]b_b{b}b~bacbccc%d'd(d[ [cm n ) * 2d3d0 E F S T g occ dcecfcA gchcicjckclcmcnc
638 n._width = width 2- . / : lbmbnbobUbVbWbXbYbZb0b1b2b3b4b5b'b)b+b-b]b_b{b}b~bacbccc%d'd(d[ [cm n ) * 2d3d0 E F S T g occ dcecfcA gchcicjckclcmcnc
639 n._height = height 2- . / : lbmbnbobUbVbWbXbYbZb0b1b2b3b4b5b'b)b+b-b]b_b{b}b~bacbccc%d'd(d[ [cm n ) * 2d3d0 E F S T g occ dcecfcA gchcicjckclcmcnc
640 n._pitch = pitch 2- . / : lbmbnbobUbVbWbXbYbZb0b1b2b3b4b5b'b)b+b-b]b_b{b}b~bacbccc%d'd(d[ [cm n ) * 2d3d0 E F S T g occ dcecfcA gchcicjckclcmcnc
641 return n 2- . / : lbmbnbobUbVbWbXbYbZb0b1b2b3b4b5b'b)b+b-b]b_b{b}b~bacbccc%d'd(d[ [cm n ) * 2d3d0 E F S T g occ dcecfcA gchcicjckclcmcnc
643 @staticmethod
644 cdef MemsetNode _create_from_driver(GraphNodeHandle h_node):
645 """Create by fetching params from the driver (called by _create factory)."""
646 cdef cydriver.CUgraphNode node = as_cu(h_node) 1[
647 cdef cydriver.CUDA_MEMSET_NODE_PARAMS params
648 with nogil: 1[
649 HANDLE_RETURN(cydriver.cuGraphMemsetNodeGetParams(node, ¶ms)) 1[
650 return MemsetNode._create_with_params( 1[
651 h_node, params.dst, params.value,
652 params.elementSize, params.width, params.height, params.pitch) 1[
654 def __repr__(self) -> str:
655 return (f"<MemsetNode handle=0x{as_intptr(self._h_node):x}" 2ig
656 f" dptr=0x{self._dptr:x} value={self._value}>") 2ig
658 def update(
659 self,
660 *,
661 dst: Buffer | int | None = None,
662 value=None,
663 width: int | None = None,
664 height: int | None = None,
665 pitch: int | None = None,
666 dst_owner=None,
667 ) -> None:
668 """Replace selected memset parameters.
670 Omitted parameters preserve their current values. ``dst_owner`` may
671 only accompany a raw-address ``dst``.
673 With drivers from CUDA 12.2 through 13.1, the node's intended CUDA
674 context must be current when this method runs. With the CUDA 13 build
675 of ``cuda.core`` and a driver of CUDA 13.2 or newer, this method
676 preserves the recorded context.
678 .. warning::
680 Use caution when a retained operand owner directly or indirectly
681 owns a graph. Any reference cycle involving the owner and a graph
682 that retains it cannot be broken by Python's cyclic garbage
683 collector. Use a weak reference to break such cycles.
684 """
685 cdef OpaqueHandle dst_attachment_owner
686 GN_check_valid(self) 2m n ) * 2d3dS T g c
687 cdef GraphHandle h_graph
688 cdef cydriver.CUgraphNode node = as_cu(self._h_node) 1mn)*STgc
689 cdef cydriver.CUcontext ctx = NULL 1mn)*STgc
690 cdef cydriver.CUDA_MEMSET_NODE_PARAMS current
691 cdef cydriver.CUgraphNodeParams params
692 cdef cydriver.CUgraphNodeParams queried # no-cython-lint
694 if dst is None and dst_owner is not None: 1mn)*STgc
695 raise ValueError("dst_owner requires dst") 1g
696 if (dst is None and value is None and width is None and 1mn)*STgc
697 height is None and pitch is None): 1g
698 return 1g
700 c_memset(¶ms, 0, sizeof(params)) 1mn)*STgc
701 params.type = cydriver.CU_GRAPH_NODE_TYPE_MEMSET 1mn)*STgc
702 with nogil: 1mn)*STgc
703 HANDLE_RETURN(cydriver.cuGraphMemsetNodeGetParams( 1mn)*STgc
704 node, ¤t))
705 IF CUDA_CORE_BUILD_MAJOR >= 13:
706 if _check_node_get_params(): 1mn)*STgc
707 _node_get_params(node, &queried) 1mn)*STgc
708 ctx = queried.memset.ctx 1mn)*STgc
709 else:
710 with nogil:
711 HANDLE_RETURN(cydriver.cuCtxGetCurrent(&ctx))
712 ELSE:
713 with nogil:
714 HANDLE_RETURN(cydriver.cuCtxGetCurrent(&ctx))
716 cdef cydriver.CUdeviceptr c_dst = current.dst 1mn)*STgc
717 cdef unsigned int c_value = current.value 1mn)*STgc
718 cdef unsigned int c_element_size = current.elementSize 1mn)*STgc
719 cdef size_t c_width = current.width 1mn)*STgc
720 cdef size_t c_height = current.height 1mn)*STgc
721 cdef size_t c_pitch = current.pitch 1mn)*STgc
723 if dst is None: 1mn)*STgc
724 h_graph = graph_node_get_graph(self._h_node) 1nSTgc
725 HANDLE_RETURN(graph_get_attachment( 1nSTgc
726 h_graph, node,
727 &dst_attachment_owner, NULL))
728 else:
729 dst_attachment_owner = _resolve_memcpy_operand( 1m)*
730 dst, dst_owner, "dst", &c_dst) 1m)*
732 if value is not None: 1mnSTgc
733 c_value, c_element_size = _parse_fill_value(value) 1mnSTc
734 if width is not None: 1mngc
735 c_width = width 1g
736 if height is not None: 1mngc
737 c_height = height 1g
738 if pitch is not None: 1mngc
739 c_pitch = pitch 1g
741 params.memset.dst = c_dst 1mngc
742 params.memset.value = c_value 1mngc
743 params.memset.elementSize = c_element_size 1mngc
744 params.memset.width = c_width 1mngc
745 params.memset.height = c_height 1mngc
746 params.memset.pitch = c_pitch 1mngc
747 params.memset.ctx = ctx 1mngc
749 _set_definition_node_params( 1mngc
750 self._h_node, ¶ms, dst_attachment_owner,
751 OpaqueHandle(), params.memset.ctx)
752 self._dptr = c_dst 1mngc
753 self._value = c_value 1mngc
754 self._element_size = c_element_size 1mngc
755 self._width = c_width 1mngc
756 self._height = c_height 1mngc
757 self._pitch = c_pitch 1mngc
759 @property
760 def dptr(self) -> int:
761 """The destination device pointer."""
762 return self._dptr 2`e{e|e}ecbdbebfb[cm n E F S T
764 @property
765 def value(self) -> int:
766 """The fill value."""
767 return self._value 2`e{e|e}ecbdbebfb[cm n E F S T g
769 @property
770 def element_size(self) -> int:
771 """Element size in bytes (1, 2, or 4)."""
772 return self._element_size 2`e{e|e}ecbdbebfbm n E F S T
774 @property
775 def width(self) -> int:
776 """Width of the row in elements."""
777 return self._width 2`e{e|e}ecbdbebfb[cm n E F S T g
779 @property
780 def height(self) -> int:
781 """Number of rows."""
782 return self._height 2`e{e|e}ecbdbebfbm n E F S T g
784 @property
785 def pitch(self) -> int:
786 """Pitch in bytes (unused if height is 1)."""
787 return self._pitch 2`e{e|e}ecbdbebfbm n E F S T g
790cdef class MemcpyNode(GraphNode):
791 """A memcpy node.
793 Properties
794 ----------
795 dst : int
796 The destination pointer.
797 src : int
798 The source pointer.
799 size : int
800 The number of bytes copied.
801 """
803 @staticmethod
804 cdef MemcpyNode _create_with_params(GraphNodeHandle h_node,
805 cydriver.CUdeviceptr dst, cydriver.CUdeviceptr src,
806 size_t size, cydriver.CUmemorytype dst_type,
807 cydriver.CUmemorytype src_type):
808 """Create from known params (called by memcpy() builder)."""
809 cdef MemcpyNode n = MemcpyNode.__new__(MemcpyNode) 2- . / : sbtbubvbwbxbNeOe8 ibIcJcPeQeReSeTeUeVeh l i v w x SdTdUdu Z G H I r s t j k a b d e f 4 g occ ybzbAbA BbCbDbEbFbGbHbIb
810 n._h_node = h_node 2- . / : sbtbubvbwbxbNeOe8 ibIcJcPeQeReSeTeUeVeh l i v w x SdTdUdu Z G H I r s t j k a b d e f 4 g occ ybzbAbA BbCbDbEbFbGbHbIb
811 n._dst = dst 2- . / : sbtbubvbwbxbNeOe8 ibIcJcPeQeReSeTeUeVeh l i v w x SdTdUdu Z G H I r s t j k a b d e f 4 g occ ybzbAbA BbCbDbEbFbGbHbIb
812 n._src = src 2- . / : sbtbubvbwbxbNeOe8 ibIcJcPeQeReSeTeUeVeh l i v w x SdTdUdu Z G H I r s t j k a b d e f 4 g occ ybzbAbA BbCbDbEbFbGbHbIb
813 n._size = size 2- . / : sbtbubvbwbxbNeOe8 ibIcJcPeQeReSeTeUeVeh l i v w x SdTdUdu Z G H I r s t j k a b d e f 4 g occ ybzbAbA BbCbDbEbFbGbHbIb
814 n._dst_type = dst_type 2- . / : sbtbubvbwbxbNeOe8 ibIcJcPeQeReSeTeUeVeh l i v w x SdTdUdu Z G H I r s t j k a b d e f 4 g occ ybzbAbA BbCbDbEbFbGbHbIb
815 n._src_type = src_type 2- . / : sbtbubvbwbxbNeOe8 ibIcJcPeQeReSeTeUeVeh l i v w x SdTdUdu Z G H I r s t j k a b d e f 4 g occ ybzbAbA BbCbDbEbFbGbHbIb
816 return n 2- . / : sbtbubvbwbxbNeOe8 ibIcJcPeQeReSeTeUeVeh l i v w x SdTdUdu Z G H I r s t j k a b d e f 4 g occ ybzbAbA BbCbDbEbFbGbHbIb
818 @staticmethod
819 cdef MemcpyNode _create_from_driver(GraphNodeHandle h_node):
820 """Create by fetching params from the driver (called by _create factory)."""
821 cdef cydriver.CUgraphNode node = as_cu(h_node) 28 ibu a b d e f
822 cdef cydriver.CUDA_MEMCPY3D params
823 with nogil: 28 ibu a b d e f
824 HANDLE_RETURN(cydriver.cuGraphMemcpyNodeGetParams(node, ¶ms)) 28 ibu a b d e f
826 cdef cydriver.CUdeviceptr dst
827 cdef cydriver.CUdeviceptr src
828 if params.dstMemoryType == cydriver.CU_MEMORYTYPE_HOST: 28 ibu a b d e f
829 dst = <cydriver.CUdeviceptr><uintptr_t>params.dstHost 2ib
830 else:
831 dst = params.dstDevice 18uabdef
832 if params.srcMemoryType == cydriver.CU_MEMORYTYPE_HOST: 28 ibu a b d e f
833 src = <cydriver.CUdeviceptr><uintptr_t>params.srcHost 2ib
834 else:
835 src = params.srcDevice 18uabdef
837 return MemcpyNode._create_with_params( 28 ibu a b d e f
838 h_node, dst, src, params.WidthInBytes,
839 params.dstMemoryType, params.srcMemoryType) 28 ibu a b d e f
841 def __repr__(self) -> str:
842 cdef str dt = _memcpy_memory_type_tag(self._dst_type) 2f 1e
843 cdef str st = _memcpy_memory_type_tag(self._src_type) 2f 1e
844 return (f"<MemcpyNode handle=0x{as_intptr(self._h_node):x}" 2f 1e
845 f" dst=0x{self._dst:x}({dt}) src=0x{self._src:x}({st}) size={self._size}>") 2f 1e
847 def update(
848 self,
849 *,
850 dst: Buffer | int | None = None,
851 src: Buffer | int | None = None,
852 size: int | None = None,
853 dst_owner=None,
854 src_owner=None,
855 ) -> None:
856 """Replace selected memcpy parameters.
858 Omitted parameters preserve their current values. ``dst_owner`` and
859 ``src_owner`` may only accompany their corresponding raw addresses.
860 Multidimensional, pitched, offset, and array-backed memcpy nodes are
861 not supported. Nodes recorded by stream capture are supported.
863 With drivers from CUDA 12.2 through 13.1, the node's intended CUDA
864 context must be current when this method runs. With the CUDA 13 build
865 of ``cuda.core`` and a driver of CUDA 13.2 or newer, this method
866 preserves the recorded context.
868 .. warning::
870 Use caution when a retained operand owner directly or indirectly
871 owns a graph. Any reference cycle involving the owner and a graph
872 that retains it cannot be broken by Python's cyclic garbage
873 collector. Use a weak reference to break such cycles.
874 """
875 cdef cydriver.CUdeviceptr c_dst = self._dst 2h l i v w x SdTdUdr s t j k a b d e f 4 g c
876 cdef cydriver.CUdeviceptr c_src = self._src 2h l i v w x SdTdUdr s t j k a b d e f 4 g c
877 cdef OpaqueHandle dst_attachment_owner
878 cdef OpaqueHandle src_attachment_owner
879 GN_check_valid(self) 2h l i v w x SdTdUdr s t j k a b d e f 4 g c
880 cdef GraphHandle h_graph = graph_node_get_graph(self._h_node) 1hlivwxrstjkabdef4gc
881 cdef cydriver.CUgraphNode node = as_cu(self._h_node) 1hlivwxrstjkabdef4gc
882 cdef cydriver.CUcontext ctx = NULL 1hlivwxrstjkabdef4gc
883 cdef cydriver.CUgraphNodeParams params
884 cdef cydriver.CUmemorytype c_dst_type
885 cdef cydriver.CUmemorytype c_src_type
886 cdef cydriver.CUgraphNodeParams queried # no-cython-lint
888 if dst is None and dst_owner is not None: 1hlivwxrstjkabdef4gc
889 raise ValueError("dst_owner requires dst") 1g
890 if src is None and src_owner is not None: 1hlivwxrstjkabdef4gc
891 raise ValueError("src_owner requires src") 1g
892 if dst is None and src is None and size is None: 1hlivwxrstjkabdef4gc
893 return 1g
895 c_memset(¶ms, 0, sizeof(params)) 1hlivwxrstjkabdef4c
896 params.type = cydriver.CU_GRAPH_NODE_TYPE_MEMCPY 1hlivwxrstjkabdef4c
897 with nogil: 1hlivwxrstjkabdef4c
898 HANDLE_RETURN(cydriver.cuGraphMemcpyNodeGetParams( 1hlivwxrstjkabdef4c
899 node, ¶ms.memcpy.copyParams))
900 IF CUDA_CORE_BUILD_MAJOR >= 13:
901 if _check_node_get_params(): 1hlivwxrstjkabdef4c
902 _node_get_params(node, &queried) 1hlivwxrstjkabdef4c
903 ctx = queried.memcpy.copyCtx 1hlivwxrstjkabdef4c
904 else:
905 with nogil:
906 HANDLE_RETURN(cydriver.cuCtxGetCurrent(&ctx))
907 ELSE:
908 with nogil:
909 HANDLE_RETURN(cydriver.cuCtxGetCurrent(&ctx))
910 params.memcpy.copyCtx = ctx 1hlivwxrstjkabdef4c
912 if not _is_supported_memcpy_descriptor(¶ms.memcpy.copyParams): 1hlivwxrstjkabdef4c
913 raise NotImplementedError( 14
914 "updating multidimensional, pitched, offset, or array-backed "
915 "memcpy nodes is not supported")
917 # The descriptor check above admits HOST, DEVICE, and UNIFIED operands;
918 # the last two keep their address in the device-pointer field.
919 c_dst_type = params.memcpy.copyParams.dstMemoryType 1hlivwxrstjkabdefc
920 c_src_type = params.memcpy.copyParams.srcMemoryType 1hlivwxrstjkabdefc
921 if c_dst_type == cydriver.CU_MEMORYTYPE_HOST: 1hlivwxrstjkabdefc
922 c_dst = <cydriver.CUdeviceptr><uintptr_t>( 1hlivwxrstjkc
923 params.memcpy.copyParams.dstHost)
924 else:
925 c_dst = params.memcpy.copyParams.dstDevice 1abdef
926 if c_src_type == cydriver.CU_MEMORYTYPE_HOST: 1hlivwxrstjkabdefc
927 c_src = <cydriver.CUdeviceptr><uintptr_t>( 1hlivwxrstjkc
928 params.memcpy.copyParams.srcHost)
929 else:
930 c_src = params.memcpy.copyParams.srcDevice 1abdef
932 HANDLE_RETURN(graph_get_attachment( 1hlivwxrstjkabdefc
933 h_graph, node,
934 &dst_attachment_owner, &src_attachment_owner))
935 # A unified operand stays unified: any address is valid for that type,
936 # and an executable update rejects a change of memory type.
937 if dst is not None: 1hlivwxrstjkabdefc
938 dst_attachment_owner = _resolve_memcpy_operand( 1hkd
939 dst, dst_owner, "dst", &c_dst)
940 if c_dst_type != cydriver.CU_MEMORYTYPE_UNIFIED: 1hkd
941 c_dst_type = _get_memcpy_memory_type(c_dst) 1hk
942 params.memcpy.copyParams.dstMemoryType = c_dst_type 1hkd
943 params.memcpy.copyParams.dstHost = NULL 1hkd
944 params.memcpy.copyParams.dstDevice = 0 1hkd
945 params.memcpy.copyParams.dstArray = NULL 1hkd
946 params.memcpy.copyParams.reserved1 = NULL 1hkd
947 if c_dst_type == cydriver.CU_MEMORYTYPE_HOST: 1hkd
948 params.memcpy.copyParams.dstHost = <void*><uintptr_t>c_dst 1h
949 else:
950 params.memcpy.copyParams.dstDevice = c_dst 1kd
951 if src is not None: 1hlivwxrstjkabdefc
952 src_attachment_owner = _resolve_memcpy_operand( 1ivwxjabe
953 src, src_owner, "src", &c_src)
954 if c_src_type != cydriver.CU_MEMORYTYPE_UNIFIED: 1ijabe
955 c_src_type = _get_memcpy_memory_type(c_src) 1ij
956 params.memcpy.copyParams.srcMemoryType = c_src_type 1ijabe
957 params.memcpy.copyParams.srcHost = NULL 1ijabe
958 params.memcpy.copyParams.srcDevice = 0 1ijabe
959 params.memcpy.copyParams.srcArray = NULL 1ijabe
960 params.memcpy.copyParams.reserved0 = NULL 1ijabe
961 if c_src_type == cydriver.CU_MEMORYTYPE_HOST: 1ijabe
962 params.memcpy.copyParams.srcHost = <void*><uintptr_t>c_src 1i
963 else:
964 params.memcpy.copyParams.srcDevice = c_src 1jabe
965 if size is not None: 1hlirstjkabdefc
966 params.memcpy.copyParams.WidthInBytes = size 1lrstfc
968 _set_definition_node_params( 1hlijkabdefc
969 self._h_node, ¶ms,
970 dst_attachment_owner, src_attachment_owner,
971 params.memcpy.copyCtx)
972 self._dst = c_dst 1hlijkabdefc
973 self._src = c_src 1hlijkabdefc
974 self._size = params.memcpy.copyParams.WidthInBytes 1hlijkabdefc
975 self._dst_type = c_dst_type 1hlijkabdefc
976 self._src_type = c_src_type 1hlijkabdefc
978 @property
979 def dst(self) -> int:
980 """The destination pointer."""
981 return self._dst 2fgab8 ibh l i G H I r s t d e f g
983 @property
984 def src(self) -> int:
985 """The source pointer."""
986 return self._src 2fgab8 ibh l i G H I r s t a b d e f g
988 @property
989 def size(self) -> int:
990 """The number of bytes copied."""
991 return self._size 2fgab8 ibh l i G H I r s t d e f g
994cdef class ChildGraphNode(GraphNode):
995 """A child graph node.
997 Properties
998 ----------
999 child_graph : GraphDefinition
1000 The embedded graph definition (non-owning wrapper).
1001 """
1003 @staticmethod
1004 cdef ChildGraphNode _create_with_params(GraphNodeHandle h_node,
1005 GraphHandle h_child_graph):
1006 """Create from known params (called by embed() builder)."""
1007 cdef ChildGraphNode n = ChildGraphNode.__new__(ChildGraphNode) 2QbAdBdCdDdEdFdGd] MbL Tf{ 4d^ ` rb| O 1dU 3 Vd]cK ; HdIdJdA KdLdMdNdOdPdQdRd
1008 n._h_node = h_node 2QbAdBdCdDdEdFdGd] MbL Tf{ 4d^ ` rb| O 1dU 3 Vd]cK ; HdIdJdA KdLdMdNdOdPdQdRd
1009 n._h_child_graph = h_child_graph 2QbAdBdCdDdEdFdGd] MbL Tf{ 4d^ ` rb| O 1dU 3 Vd]cK ; HdIdJdA KdLdMdNdOdPdQdRd
1010 return n 2QbAdBdCdDdEdFdGd] MbL Tf{ 4d^ ` rb| O 1dU 3 Vd]cK ; HdIdJdA KdLdMdNdOdPdQdRd
1012 @staticmethod
1013 cdef ChildGraphNode _create_from_driver(GraphNodeHandle h_node):
1014 """Create by fetching params from the driver (called by _create factory)."""
1015 cdef cydriver.CUgraphNode node = as_cu(h_node) 1]L{^`|O
1016 cdef cydriver.CUgraph child_graph = NULL 1]L{^`|O
1017 with nogil: 1]L{^`|O
1018 HANDLE_RETURN(cydriver.cuGraphChildGraphNodeGetGraph(node, &child_graph)) 1]L{^`|O
1019 cdef GraphHandle h_graph = graph_node_get_graph(h_node) 1]L{^`|O
1020 cdef GraphHandle h_child = create_child_graph_handle( 1]L{^`|O
1021 child_graph, h_graph, node)
1022 return ChildGraphNode._create_with_params(h_node, h_child) 1]L{^`|O
1024 def __repr__(self) -> str:
1025 return (f"<ChildGraphNode handle=0x{as_intptr(self._h_node):x}" 2] L ^ rb1dU jg
1026 f" child=0x{as_intptr(self._h_child_graph):x}>") 2] L ^ rb1dU jg
1028 def update(self, GraphDefinition child not None: GraphDefinition) -> None:
1029 """Replace the embedded graph with a clone of ``child``.
1031 ``child`` must belong to an independent graph hierarchy.
1032 """
1033 GN_check_valid(self) 2L O 3 ]c;
1034 GD_check_valid(child) 1LO3;
1035 cdef GraphHandle h_parent = graph_node_get_graph(self._h_node) 1LO3;
1036 cdef GraphHandle h_replacement
1037 cdef cydriver.CUgraphNode node = as_cu(self._h_node) 1LO3;
1038 cdef cydriver.CUgraphNodeParams params
1039 cdef cydriver.CUresult commit_status
1040 cdef PreparedChildGraphUpdate prepared
1042 _require_graph_node_update_support() 1LO3;
1043 c_memset(¶ms, 0, sizeof(params)) 1LO3;
1044 params.type = cydriver.CU_GRAPH_NODE_TYPE_GRAPH 1LO3;
1045 params.graph.graph = as_cu(child._h_graph) 1LO3;
1047 HANDLE_RETURN(graph_prepare_child_graph_update( 1LO3;
1048 h_parent, self._h_child_graph, node,
1049 child._h_graph, &prepared))
1050 with nogil: 1LO3
1051 HANDLE_RETURN(cydriver.cuGraphNodeSetParams( 1LO3
1052 node, ¶ms))
1053 try: 1LO3
1054 commit_status = graph_commit_child_graph_update( 1LO3
1055 prepared, &h_replacement)
1056 finally:
1057 if h_replacement: 1LO3
1058 self._h_child_graph = h_replacement 1LO3
1059 HANDLE_RETURN(commit_status) 1LO3
1061 @property
1062 def child_graph(self) -> GraphDefinition:
1063 """The embedded graph definition (non-owning wrapper)."""
1064 return GraphDefinition._from_handle(self._h_child_graph) 2Qbtcug] MbL Tf{ ^ ` rb| O 1d3 Vd]cK ;
1067cdef class EventRecordNode(GraphNode):
1068 """An event record node.
1070 Properties
1071 ----------
1072 event : Event
1073 The event being recorded.
1074 """
1076 @staticmethod
1077 cdef EventRecordNode _create_with_params(GraphNodeHandle h_node,
1078 EventHandle h_event):
1079 """Create from known params (called by record() builder)."""
1080 cdef EventRecordNode n = EventRecordNode.__new__(EventRecordNode) 2We)c+c-c/c;c?cUf1cVfXeYegbhbKcLcpb8 ib(c9 X 5dRbQ M 'cpc1f2f3fA 4f5f6f7f8f9f!f#f
1081 n._h_node = h_node 2We)c+c-c/c;c?cUf1cVfXeYegbhbKcLcpb8 ib(c9 X 5dRbQ M 'cpc1f2f3fA 4f5f6f7f8f9f!f#f
1082 n._h_event = h_event 2We)c+c-c/c;c?cUf1cVfXeYegbhbKcLcpb8 ib(c9 X 5dRbQ M 'cpc1f2f3fA 4f5f6f7f8f9f!f#f
1083 return n 2We)c+c-c/c;c?cUf1cVfXeYegbhbKcLcpb8 ib(c9 X 5dRbQ M 'cpc1f2f3fA 4f5f6f7f8f9f!f#f
1085 @staticmethod
1086 cdef EventRecordNode _create_from_driver(GraphNodeHandle h_node):
1087 """Create by fetching params from the driver (called by _create factory)."""
1088 cdef cydriver.CUgraphNode node = as_cu(h_node) 2Kc
1089 cdef cydriver.CUevent event
1090 with nogil: 2Kc
1091 HANDLE_RETURN(cydriver.cuGraphEventRecordNodeGetEvent(node, &event)) 2Kc
1092 cdef EventHandle h_event = create_event_handle_ref(event) 2Kc
1093 return EventRecordNode._create_with_params(h_node, h_event) 2Kc
1095 def __repr__(self) -> str:
1096 return (f"<EventRecordNode handle=0x{as_intptr(self._h_node):x}" 2kg
1097 f" event=0x{as_intptr(self._h_event):x}>") 2kg
1099 def update(self, Event event not None: Event) -> None:
1100 """Replace the event recorded by this node."""
1101 GN_check_valid(self) 29 Rb'c
1102 Event_check_open(event) 29 'c
1103 cdef OpaqueHandle event_owner = event._h_event 19
1104 cdef cydriver.CUgraphNodeParams params
1106 c_memset(¶ms, 0, sizeof(params)) 19
1107 params.type = cydriver.CU_GRAPH_NODE_TYPE_EVENT_RECORD 19
1108 params.eventRecord.event = as_cu(event._h_event) 19
1110 _set_definition_node_params( 19
1111 self._h_node, ¶ms, event_owner)
1112 self._h_event = event._h_event 19
1114 @property
1115 def event(self) -> Event:
1116 """The event being recorded."""
1117 return Event._from_handle(self._h_event) 2vgNbUf1cVfKc9 Q 'c
1120cdef class EventWaitNode(GraphNode):
1121 """An event wait node.
1123 Properties
1124 ----------
1125 event : Event
1126 The event being waited on.
1127 """
1129 @staticmethod
1130 cdef EventWaitNode _create_with_params(GraphNodeHandle h_node,
1131 EventHandle h_event):
1132 """Create from known params (called by wait() builder)."""
1133 cdef EventWaitNode n = EventWaitNode.__new__(EventWaitNode) 2We*c,c.c:c=c@cXeYe2cWfKcLcX 6dSbM pc$f%f'fA (f)f*f+f,f-f.f/f
1134 n._h_node = h_node 2We*c,c.c:c=c@cXeYe2cWfKcLcX 6dSbM pc$f%f'fA (f)f*f+f,f-f.f/f
1135 n._h_event = h_event 2We*c,c.c:c=c@cXeYe2cWfKcLcX 6dSbM pc$f%f'fA (f)f*f+f,f-f.f/f
1136 return n 2We*c,c.c:c=c@cXeYe2cWfKcLcX 6dSbM pc$f%f'fA (f)f*f+f,f-f.f/f
1138 @staticmethod
1139 cdef EventWaitNode _create_from_driver(GraphNodeHandle h_node):
1140 """Create by fetching params from the driver (called by _create factory)."""
1141 cdef cydriver.CUgraphNode node = as_cu(h_node) 2Lc
1142 cdef cydriver.CUevent event
1143 with nogil: 2Lc
1144 HANDLE_RETURN(cydriver.cuGraphEventWaitNodeGetEvent(node, &event)) 2Lc
1145 cdef EventHandle h_event = create_event_handle_ref(event) 2Lc
1146 return EventWaitNode._create_with_params(h_node, h_event) 2Lc
1148 def __repr__(self) -> str:
1149 return (f"<EventWaitNode handle=0x{as_intptr(self._h_node):x}" 2lg
1150 f" event=0x{as_intptr(self._h_event):x}>") 2lg
1152 def update(self, Event event not None: Event) -> None:
1153 """Replace the event waited on by this node."""
1154 GN_check_valid(self) 2X Sbpc
1155 Event_check_open(event) 2X pc
1156 cdef OpaqueHandle event_owner = event._h_event 1X
1157 cdef cydriver.CUgraphNodeParams params
1159 c_memset(¶ms, 0, sizeof(params)) 1X
1160 params.type = cydriver.CU_GRAPH_NODE_TYPE_WAIT_EVENT 1X
1161 params.eventWait.event = as_cu(event._h_event) 1X
1163 _set_definition_node_params( 1X
1164 self._h_node, ¶ms, event_owner)
1165 self._h_event = event._h_event 1X
1167 @property
1168 def event(self) -> Event:
1169 """The event being waited on."""
1170 return Event._from_handle(self._h_event) 2wgOb2cWfLcX M pc
1173cdef class HostCallbackNode(GraphNode):
1174 """A host callback node.
1176 Properties
1177 ----------
1178 callback : callable or None
1179 The Python callable (None for ctypes function pointer callbacks).
1180 """
1182 @staticmethod
1183 cdef HostCallbackNode _create_with_params(GraphNodeHandle h_node,
1184 object callable_obj, cydriver.CUhostFn fn,
1185 void* user_data):
1186 """Create from known params (called by callback() builder)."""
1187 cdef HostCallbackNode n = HostCallbackNode.__new__(HostCallbackNode) 2~eafbfcfdfZeQbefffgfhfifjfkflfmfnfofpfqfrfsf] tfufvfwfL { 4d! 6 # $ % 7 ' ( IcJc^ xfrbyf| O zfHcU y 7d3 9 X + , Vd5d6dAf0e]cRbSb@e[eY K Q M V W 1 ; 'cpc)d*dR z 2 P 8d9dBfCfDfEfA FfGfHfIfJfKfLfMf
1188 n._h_node = h_node 2~eafbfcfdfZeQbefffgfhfifjfkflfmfnfofpfqfrfsf] tfufvfwfL { 4d! 6 # $ % 7 ' ( IcJc^ xfrbyf| O zfHcU y 7d3 9 X + , Vd5d6dAf0e]cRbSb@e[eY K Q M V W 1 ; 'cpc)d*dR z 2 P 8d9dBfCfDfEfA FfGfHfIfJfKfLfMf
1189 n._callable = callable_obj 2~eafbfcfdfZeQbefffgfhfifjfkflfmfnfofpfqfrfsf] tfufvfwfL { 4d! 6 # $ % 7 ' ( IcJc^ xfrbyf| O zfHcU y 7d3 9 X + , Vd5d6dAf0e]cRbSb@e[eY K Q M V W 1 ; 'cpc)d*dR z 2 P 8d9dBfCfDfEfA FfGfHfIfJfKfLfMf
1190 n._fn = fn 2~eafbfcfdfZeQbefffgfhfifjfkflfmfnfofpfqfrfsf] tfufvfwfL { 4d! 6 # $ % 7 ' ( IcJc^ xfrbyf| O zfHcU y 7d3 9 X + , Vd5d6dAf0e]cRbSb@e[eY K Q M V W 1 ; 'cpc)d*dR z 2 P 8d9dBfCfDfEfA FfGfHfIfJfKfLfMf
1191 n._user_data = user_data 2~eafbfcfdfZeQbefffgfhfifjfkflfmfnfofpfqfrfsf] tfufvfwfL { 4d! 6 # $ % 7 ' ( IcJc^ xfrbyf| O zfHcU y 7d3 9 X + , Vd5d6dAf0e]cRbSb@e[eY K Q M V W 1 ; 'cpc)d*dR z 2 P 8d9dBfCfDfEfA FfGfHfIfJfKfLfMf
1192 return n 2~eafbfcfdfZeQbefffgfhfifjfkflfmfnfofpfqfrfsf] tfufvfwfL { 4d! 6 # $ % 7 ' ( IcJc^ xfrbyf| O zfHcU y 7d3 9 X + , Vd5d6dAf0e]cRbSb@e[eY K Q M V W 1 ; 'cpc)d*dR z 2 P 8d9dBfCfDfEfA FfGfHfIfJfKfLfMf
1194 @staticmethod
1195 cdef HostCallbackNode _create_from_driver(GraphNodeHandle h_node):
1196 """Create by fetching params from the driver (called by _create factory)."""
1197 cdef cydriver.CUgraphNode node = as_cu(h_node) 2Qb] L { ^ rb| O 3 RbSbK ;
1198 cdef cydriver.CUDA_HOST_NODE_PARAMS params
1199 with nogil: 2Qb] L { ^ rb| O 3 RbSbK ;
1200 HANDLE_RETURN(cydriver.cuGraphHostNodeGetParams(node, ¶ms)) 2Qb] L { ^ rb| O 3 RbSbK ;
1202 cdef object callable_obj = None 2Qb] L { ^ rb| O 3 RbSbK ;
1203 if _is_py_host_trampoline(params.fn): 2Qb] L { ^ rb| O 3 RbSbK ;
1204 callable_obj = <object>params.userData 2Qb] L { ^ rb| O 3 RbSbK ;
1206 return HostCallbackNode._create_with_params( 2Qb] L { ^ rb| O 3 RbSbK ;
1207 h_node, callable_obj, params.fn, params.userData) 2Qb] L { ^ rb| O 3 RbSbK ;
1209 def __repr__(self) -> str:
1210 if self._callable is not None: 27dP :f
1211 name = getattr(self._callable, '__name__', '?') 2P :f
1212 return (f"<HostCallbackNode handle=0x{as_intptr(self._h_node):x}" 2P :f
1213 f" callback={name}>") 2P :f
1214 return (f"<HostCallbackNode handle=0x{as_intptr(self._h_node):x}" 27d
1215 f" cfunc=0x{<uintptr_t>self._fn:x}>") 27d
1217 def update(self, fn, *, user_data=None) -> None:
1218 """Replace the callback and user-data binding for this node.
1220 ``fn`` accepts the same forms as :meth:`~graph.GraphNode.callback`: a
1221 Python callable, or a ctypes function pointer whose declared prototype
1222 matches ``CUhostFn`` (``void (*)(void*)``). A mismatched ctypes
1223 prototype raises ``TypeError``.
1225 .. warning::
1227 Callbacks must not call CUDA API functions. Doing so may
1228 deadlock or corrupt driver state.
1230 Use caution when a Python callback retains an object that owns a
1231 graph. Any reference cycle involving the callback and a graph that
1232 retains it cannot be broken by Python's cyclic garbage collector.
1233 Use a weak reference to break such cycles.
1234 """
1235 GN_check_valid(self) 2Ze+ , 0e@e[e)d*d
1236 cdef cydriver.CUhostFn c_fn
1237 cdef void* c_user_data
1238 cdef OpaqueHandle fn_owner, data_owner
1239 cdef cydriver.CUgraphNodeParams params
1241 _resolve_host_callback( 2Ze+ , 0e)d*d
1242 fn, user_data, &c_fn, &c_user_data, &fn_owner, &data_owner)
1243 c_memset(¶ms, 0, sizeof(params)) 1+,
1244 params.type = cydriver.CU_GRAPH_NODE_TYPE_HOST 1+,
1245 params.host.fn = c_fn 1+,
1246 params.host.userData = c_user_data 1+,
1248 _set_definition_node_params( 1+,
1249 self._h_node, ¶ms, fn_owner, data_owner)
1250 self._callable = fn if _is_py_host_trampoline(c_fn) else None 1+,
1251 self._fn = c_fn 1+,
1252 self._user_data = c_user_data 1+,
1254 @property
1255 def callback(self):
1256 """The Python callable, or None for ctypes function pointer callbacks."""
1257 return self._callable 2xgygL 7d3 + , K V W ; )d*d
1260cdef class ConditionalNode(GraphNode):
1261 """Base class for conditional nodes.
1263 When created via builder methods (if_then, if_else, while_loop, switch),
1264 a specific subclass (IfNode, IfElseNode, WhileNode, SwitchNode) is
1265 returned. When reconstructed from the driver on CUDA 13.2+, the
1266 correct subclass is determined via cuGraphNodeGetParams. On older
1267 drivers, this base class is used as a fallback.
1269 Properties
1270 ----------
1271 condition : GraphCondition or None
1272 The condition variable controlling execution (None pre-13.2).
1273 cond_type : str or None
1274 The conditional type ("if", "while", or "switch"; None pre-13.2).
1275 branches : tuple of GraphDefinition
1276 The body graphs for each branch (empty pre-13.2).
1277 """
1279 @staticmethod
1280 cdef ConditionalNode _create_from_driver(GraphNodeHandle h_node):
1281 cdef ConditionalNode n
1282 if not _check_node_get_params(): 1!6#$%7'(@
1283 n = ConditionalNode.__new__(ConditionalNode)
1284 n._h_node = h_node
1285 n._condition = None
1286 n._cond_type = cydriver.CU_GRAPH_COND_TYPE_IF
1287 n._branches = ()
1288 return n
1289 IF CUDA_CORE_BUILD_MAJOR >= 13:
1290 return ConditionalNode._create_from_driver_params(h_node) 1!6#$%7'(@
1291 ELSE:
1292 raise AssertionError("unreachable: cuGraphNodeGetParams needs the CUDA 13 build")
1294 IF CUDA_CORE_BUILD_MAJOR >= 13:
1295 @staticmethod
1296 cdef ConditionalNode _create_from_driver_params(GraphNodeHandle h_node):
1297 cdef ConditionalNode n
1298 cdef cydriver.CUgraphNode node = as_cu(h_node) 1!6#$%7'(@
1299 cdef cydriver.CUgraphNodeParams params
1300 _node_get_params(node, ¶ms) 1!6#$%7'(@
1301 cdef int cond_type_int = <int>params.conditional.type 1!6#$%7'(@
1302 cdef unsigned int size = params.conditional.size 1!6#$%7'(@
1304 cdef GraphCondition condition = GraphCondition.__new__(GraphCondition) 1!6#$%7'(@
1305 condition._c_handle = params.conditional.handle 1!6#$%7'(@
1307 cdef GraphHandle h_graph = graph_node_get_graph(h_node) 1!6#$%7'(@
1308 cdef list branch_list = [] 1!6#$%7'(@
1309 cdef unsigned int i
1310 cdef GraphHandle h_branch
1311 if params.conditional.phGraph_out != NULL: 1!6#$%7'(@
1312 for i in range(size): 1!6#$%7'(@
1313 h_branch = create_child_graph_handle( 1!6#$%7'(@
1314 params.conditional.phGraph_out[i], h_graph, node)
1315 branch_list.append(GraphDefinition._from_handle(h_branch)) 1!6#$%7'(@
1316 cdef tuple branches = tuple(branch_list) 1!6#$%7'(@
1318 cdef type cls
1319 if cond_type_int == <int>cydriver.CU_GRAPH_COND_TYPE_IF: 1!6#$%7'(@
1320 if size == 1: 1!6%7
1321 cls = IfNode 1!%
1322 else:
1323 cls = IfElseNode 167
1324 elif cond_type_int == <int>cydriver.CU_GRAPH_COND_TYPE_WHILE: 1#$'(@
1325 cls = WhileNode 1$(@
1326 else:
1327 cls = SwitchNode 1#'
1329 n = cls.__new__(cls) 1!6#$%7'(@
1330 n._h_node = h_node 1!6#$%7'(@
1331 n._condition = condition 1!6#$%7'(@
1332 n._cond_type = <cydriver.CUgraphConditionalNodeType>cond_type_int 1!6#$%7'(@
1333 n._branches = branches 1!6#$%7'(@
1334 return n 1!6#$%7'(@
1336 def __repr__(self) -> str:
1337 return f"<ConditionalNode handle=0x{as_intptr(self._h_node):x}>"
1339 @property
1340 def condition(self) -> GraphCondition | None:
1341 """The condition variable controlling execution."""
1342 return self._condition 2]eNfXfOf^ePfYfQf
1344 @property
1345 def cond_type(self) -> GraphConditionalType | None:
1346 """The conditional type: GraphConditionalType.IF, .WHILE, or .SWITCH
1348 Returns None when reconstructed from the driver pre-CUDA 13.2,
1349 as the conditional type cannot be determined.
1350 """
1351 if self._condition is None: 2]eNfXfOf^ePfYfQf
1352 return None
1353 if self._cond_type == cydriver.CU_GRAPH_COND_TYPE_IF: 2]eNfXfOf^ePfYfQf
1354 return GraphConditionalType("if") 2]eNf^ePf
1355 elif self._cond_type == cydriver.CU_GRAPH_COND_TYPE_WHILE:
1356 return GraphConditionalType("while") 2OfQf
1357 else:
1358 return GraphConditionalType("switch") 2XfYf
1360 @property
1361 def branches(self) -> tuple[GraphDefinition, ...]:
1362 """The body graphs for each branch as a tuple of GraphDefinition.
1364 Returns an empty tuple when reconstructed from the driver
1365 pre-CUDA 13.2.
1366 """
1367 return self._branches 2]eNfXfOf^ePfYfQfzgBc# ' @
1370cdef class IfNode(ConditionalNode):
1371 """An if-conditional node."""
1373 def __repr__(self) -> str:
1374 return (f"<IfNode handle=0x{as_intptr(self._h_node):x}" 2mg
1375 f" condition=0x{<unsigned long long>self._condition._c_handle:x}>") 2mg
1377 @property
1378 def then(self) -> GraphDefinition:
1379 """The 'then' branch graph."""
1380 return self._branches[0] 2NfPfAgAc! %
1383cdef class IfElseNode(ConditionalNode):
1384 """An if-else conditional node."""
1386 def __repr__(self) -> str:
1387 return (f"<IfElseNode handle=0x{as_intptr(self._h_node):x}" 2ng
1388 f" condition=0x{<unsigned long long>self._condition._c_handle:x}>") 2ng
1390 @property
1391 def then(self) -> GraphDefinition:
1392 """The ``then`` branch graph (executed when condition is non-zero)."""
1393 return self._branches[0] 2]e^eogqc6 7
1395 @property
1396 def else_(self) -> GraphDefinition:
1397 """The ``else`` branch graph (executed when condition is zero)."""
1398 return self._branches[1] 2]e^eogqc6 7
1401cdef class WhileNode(ConditionalNode):
1402 """A while-loop conditional node."""
1404 def __repr__(self) -> str:
1405 return (f"<WhileNode handle=0x{as_intptr(self._h_node):x}" 2pg
1406 f" condition=0x{<unsigned long long>self._condition._c_handle:x}>") 2pg
1408 @property
1409 def body(self) -> GraphDefinition:
1410 """The loop body graph."""
1411 return self._branches[0] 2OfQfBgCc$ (
1414cdef class SwitchNode(ConditionalNode):
1415 """A switch conditional node."""
1417 def __repr__(self) -> str:
1418 return (f"<SwitchNode handle=0x{as_intptr(self._h_node):x}" 2qg
1419 f" condition=0x{<unsigned long long>self._condition._c_handle:x}>") 2qg
1422cdef class ExecutableGraphNode:
1423 """A lightweight view pairing an executable graph with a source node.
1425 Create executable-node views with ``graph[node]``. CUDA validates that the
1426 node identifies a node in the executable graph when an operation is
1427 performed.
1428 """
1430 def __init__(self):
1431 raise RuntimeError( 2Cg
1432 "directly constructing an executable graph node is not supported")
1434 def __repr__(self) -> str:
1435 return ( 2Tb
1436 f"<{type(self).__name__} graph=0x{as_intptr(self._h_graph_exec):x}" 2Tb
1437 f" node=0x{as_intptr(self._h_node):x}>" 2Tb
1438 )
1441cdef class ExecutableKernelNode(ExecutableGraphNode):
1442 """An executable kernel-node view."""
1444 def update(
1445 self,
1446 *,
1447 LaunchConfig config not None: LaunchConfig,
1448 Kernel kernel not None: Kernel,
1449 args,
1450 ) -> None:
1451 """Replace all kernel launch parameters for future launches.
1453 ``args`` must contain the complete argument sequence; use ``args=()``
1454 for a no-argument kernel. Clustered and cooperative launch
1455 configurations are not supported.
1456 """
1457 cdef LaunchConfig c_config = config 2y N JbKbB C D z J
1458 cdef Kernel c_kernel = kernel 2y N JbKbB C D z J
1459 cdef ParamHolder arg_holder
1460 cdef object kernel_args
1461 cdef OpaqueHandle kernel_owner = c_kernel._h_kernel 2y N JbKbB C D z J
1462 cdef OpaqueHandle args_owner
1463 cdef cydriver.CUgraphNodeParams params
1465 if c_config.cluster is not None or c_config.is_cooperative: 2y N JbKbB C D z J
1466 raise NotImplementedError( 2JbKb
1467 "updating clustered or cooperative kernel nodes is not "
1468 "supported")
1469 arg_holder = ParamHolder(args) 1yNBCDzJ
1471 c_memset(¶ms, 0, sizeof(params)) 1yNBCDzJ
1472 params.type = cydriver.CU_GRAPH_NODE_TYPE_KERNEL 1yNBCDzJ
1473 params.kernel.kern = as_cu(c_kernel._h_kernel) 1yNBCDzJ
1474 params.kernel.func = <cydriver.CUfunction>NULL 1yNBCDzJ
1475 params.kernel.gridDimX = c_config.grid[0] 1yNBCDzJ
1476 params.kernel.gridDimY = c_config.grid[1] 1yNBCDzJ
1477 params.kernel.gridDimZ = c_config.grid[2] 1yNBCDzJ
1478 params.kernel.blockDimX = c_config.block[0] 1yNBCDzJ
1479 params.kernel.blockDimY = c_config.block[1] 1yNBCDzJ
1480 params.kernel.blockDimZ = c_config.block[2] 1yNBCDzJ
1481 params.kernel.sharedMemBytes = c_config.shmem_size 1yNBCDzJ
1482 params.kernel.kernelParams = <void**><uintptr_t>arg_holder.ptr 1yNBCDzJ
1483 params.kernel.extra = NULL 1yNBCDzJ
1484 params.kernel.ctx = <cydriver.CUcontext>NULL 1yNBCDzJ
1486 kernel_args = arg_holder.kernel_args 1yNBCDzJ
1487 if kernel_args is not None: 1yNBCDzJ
1488 args_owner = make_opaque_py(kernel_args) 1yBCzJ
1489 _set_executable_node_params( 1yNBCDzJ
1490 self._h_graph_exec, self._h_node, ¶ms,
1491 kernel_owner, args_owner)
1493 @property
1494 def is_enabled(self) -> bool:
1495 """Whether this node is enabled in the executable graph."""
1496 return _get_executable_node_enabled( 1}5
1497 self._h_graph_exec, self._h_node) 1}5
1499 def enable(self) -> None:
1500 """Enable this node in the executable graph."""
1501 _set_executable_node_enabled( 1~5
1502 self._h_graph_exec, self._h_node, True)
1504 def disable(self) -> None:
1505 """Disable this node in the executable graph."""
1506 _set_executable_node_enabled( 15
1507 self._h_graph_exec, self._h_node, False)
1510cdef class ExecutableMemsetNode(ExecutableGraphNode):
1511 """An executable memset-node view."""
1513 def update(
1514 self,
1515 *,
1516 dst: Buffer | int,
1517 value,
1518 size_t width,
1519 size_t height=1,
1520 size_t pitch=0,
1521 ) -> None:
1522 """Replace all memset parameters for future launches."""
1523 cdef cydriver.CUdeviceptr c_dst
1524 cdef OpaqueHandle dst_owner = _resolve_memcpy_operand( 1EF
1525 dst, None, "dst", &c_dst)
1526 cdef unsigned int c_value
1527 cdef unsigned int element_size
1528 c_value, element_size = _parse_fill_value(value) 1EF
1530 cdef cydriver.CUcontext ctx = NULL 1EF
1531 cdef cydriver.CUgraphNodeParams params
1532 with nogil: 1EF
1533 HANDLE_RETURN(cydriver.cuCtxGetCurrent(&ctx)) 1EF
1535 c_memset(¶ms, 0, sizeof(params)) 1EF
1536 params.type = cydriver.CU_GRAPH_NODE_TYPE_MEMSET 1EF
1537 params.memset.dst = c_dst 1EF
1538 params.memset.value = c_value 1EF
1539 params.memset.elementSize = element_size 1EF
1540 params.memset.width = width 1EF
1541 params.memset.height = height 1EF
1542 params.memset.pitch = pitch 1EF
1543 params.memset.ctx = ctx 1EF
1544 _set_executable_node_params( 1EF
1545 self._h_graph_exec, self._h_node, ¶ms, dst_owner)
1547 @property
1548 def is_enabled(self) -> bool:
1549 """Whether this node is enabled in the executable graph."""
1550 return _get_executable_node_enabled( 10
1551 self._h_graph_exec, self._h_node) 10
1553 def enable(self) -> None:
1554 """Enable this node in the executable graph."""
1555 _set_executable_node_enabled( 10
1556 self._h_graph_exec, self._h_node, True)
1558 def disable(self) -> None:
1559 """Disable this node in the executable graph."""
1560 _set_executable_node_enabled( 10
1561 self._h_graph_exec, self._h_node, False)
1564cdef class ExecutableMemcpyNode(ExecutableGraphNode):
1565 """An executable memcpy-node view."""
1567 def update(
1568 self,
1569 *,
1570 dst: Buffer | int,
1571 src: Buffer | int,
1572 size_t size,
1573 ) -> None:
1574 """Replace all one-dimensional memcpy parameters for future launches.
1576 Nodes recorded by stream capture are supported.
1577 """
1578 cdef cydriver.CUdeviceptr c_dst
1579 cdef cydriver.CUdeviceptr c_src
1580 cdef OpaqueHandle dst_owner = _resolve_memcpy_operand( 1uGHIab
1581 dst, None, "dst", &c_dst)
1582 cdef OpaqueHandle src_owner = _resolve_memcpy_operand( 1uGHIab
1583 src, None, "src", &c_src)
1584 cdef cydriver.CUmemorytype dst_type
1585 cdef cydriver.CUmemorytype src_type
1586 cdef cydriver.CUcontext ctx = NULL 1uGHIab
1587 cdef cydriver.CUgraphNodeParams params
1588 cdef cydriver.CUDA_MEMCPY3D recorded
1589 cdef cydriver.CUgraphNode node = as_cu(self._h_node) 1uGHIab
1591 c_memset(¶ms, 0, sizeof(params)) 1uGHIab
1592 params.type = cydriver.CU_GRAPH_NODE_TYPE_MEMCPY 1uGHIab
1593 _init_memcpy_params( 1uGHIab
1594 c_dst, c_src, size, ¶ms.memcpy.copyParams,
1595 &dst_type, &src_type)
1596 # A destroyed node is reported by _set_executable_node_params below.
1597 # The memory types are read from the definition node, not from the
1598 # instantiated graph. That is correct only while MemcpyNode.update()
1599 # keeps a unified operand unified, which it does; an executable update
1600 # rejects a change of memory type.
1601 if node != NULL: 1uGHIab
1602 with nogil: 1uGHIab
1603 HANDLE_RETURN(cydriver.cuGraphMemcpyNodeGetParams( 1uGHIab
1604 node, &recorded))
1605 if recorded.dstMemoryType == cydriver.CU_MEMORYTYPE_UNIFIED: 1uGHIab
1606 params.memcpy.copyParams.dstMemoryType = ( 1uab
1607 cydriver.CU_MEMORYTYPE_UNIFIED)
1608 params.memcpy.copyParams.dstHost = NULL 1uab
1609 params.memcpy.copyParams.dstDevice = c_dst 1uab
1610 if recorded.srcMemoryType == cydriver.CU_MEMORYTYPE_UNIFIED: 1uGHIab
1611 params.memcpy.copyParams.srcMemoryType = ( 1uab
1612 cydriver.CU_MEMORYTYPE_UNIFIED)
1613 params.memcpy.copyParams.srcHost = NULL 1uab
1614 params.memcpy.copyParams.srcDevice = c_src 1uab
1615 with nogil: 1uGHIab
1616 HANDLE_RETURN(cydriver.cuCtxGetCurrent(&ctx)) 1uGHIab
1617 params.memcpy.copyCtx = ctx 1uGHIab
1618 _set_executable_node_params( 1uGHIab
1619 self._h_graph_exec, self._h_node, ¶ms,
1620 dst_owner, src_owner)
1622 @property
1623 def is_enabled(self) -> bool:
1624 """Whether this node is enabled in the executable graph."""
1625 return _get_executable_node_enabled( 1Z
1626 self._h_graph_exec, self._h_node) 1Z
1628 def enable(self) -> None:
1629 """Enable this node in the executable graph."""
1630 _set_executable_node_enabled( 1Z
1631 self._h_graph_exec, self._h_node, True)
1633 def disable(self) -> None:
1634 """Disable this node in the executable graph."""
1635 _set_executable_node_enabled( 1Z
1636 self._h_graph_exec, self._h_node, False)
1639cdef class ExecutableChildGraphNode(ExecutableGraphNode):
1640 """An executable child-graph-node view."""
1642 def update(self, GraphDefinition child not None: GraphDefinition) -> None:
1643 """Replace the embedded graph parameters for future launches."""
1644 GD_check_valid(child) 1UK
1645 cdef cydriver.CUgraphNodeParams params
1646 c_memset(¶ms, 0, sizeof(params)) 1UK
1647 params.type = cydriver.CU_GRAPH_NODE_TYPE_GRAPH 1UK
1648 params.graph.graph = as_cu(child._h_graph) 1UK
1649 _set_executable_node_params( 1UK
1650 self._h_graph_exec, self._h_node, ¶ms)
1653cdef class ExecutableEventRecordNode(ExecutableGraphNode):
1654 """An executable event-record-node view."""
1656 def update(self, Event event not None: Event) -> None:
1657 """Replace the event recorded by future launches."""
1658 Event_check_open(event) 1Q
1659 cdef OpaqueHandle event_owner = event._h_event 1Q
1660 cdef cydriver.CUgraphNodeParams params
1661 c_memset(¶ms, 0, sizeof(params)) 1Q
1662 params.type = cydriver.CU_GRAPH_NODE_TYPE_EVENT_RECORD 1Q
1663 params.eventRecord.event = as_cu(event._h_event) 1Q
1664 _set_executable_node_params( 1Q
1665 self._h_graph_exec, self._h_node, ¶ms, event_owner)
1668cdef class ExecutableEventWaitNode(ExecutableGraphNode):
1669 """An executable event-wait-node view."""
1671 def update(self, Event event not None: Event) -> None:
1672 """Replace the event waited on by future launches."""
1673 Event_check_open(event) 1M
1674 cdef OpaqueHandle event_owner = event._h_event 1M
1675 cdef cydriver.CUgraphNodeParams params
1676 c_memset(¶ms, 0, sizeof(params)) 1M
1677 params.type = cydriver.CU_GRAPH_NODE_TYPE_WAIT_EVENT 1M
1678 params.eventWait.event = as_cu(event._h_event) 1M
1679 _set_executable_node_params( 1M
1680 self._h_graph_exec, self._h_node, ¶ms, event_owner)
1683cdef class ExecutableHostCallbackNode(ExecutableGraphNode):
1684 """An executable host-callback-node view."""
1686 def update(self, fn, *, user_data=None) -> None:
1687 """Replace the callback and user-data binding for future launches.
1689 ``fn`` may be a Python callable, or a ctypes function pointer whose
1690 declared prototype matches ``CUhostFn`` (``void (*)(void*)``); a
1691 mismatched prototype raises ``TypeError``.
1693 .. warning::
1695 Callbacks must not call CUDA API functions. Doing so may deadlock
1696 or corrupt driver state.
1697 """
1698 cdef cydriver.CUhostFn c_fn
1699 cdef void* c_user_data
1700 cdef OpaqueHandle fn_owner
1701 cdef OpaqueHandle data_owner
1702 cdef cydriver.CUgraphNodeParams params
1704 _resolve_host_callback( 1YVW1R2P
1705 fn, user_data, &c_fn, &c_user_data, &fn_owner, &data_owner)
1706 c_memset(¶ms, 0, sizeof(params)) 1YVW1R2P
1707 params.type = cydriver.CU_GRAPH_NODE_TYPE_HOST 1YVW1R2P
1708 params.host.fn = c_fn 1YVW1R2P
1709 params.host.userData = c_user_data 1YVW1R2P
1710 _set_executable_node_params( 1YVW1R2P
1711 self._h_graph_exec, self._h_node, ¶ms,
1712 fn_owner, data_owner)
1715cdef ExecutableGraphNode create_executable_node_view(
1716 const GraphExecHandle& h_exec,
1717 GraphNode node):
1718 cdef type view_type
1719 if isinstance(node, KernelNode): 2U y Y ~ } N JbKbu 5 Z 0 TbK Q M V W B C D G H I E F Lb1 R z a b J 2 P
1720 view_type = ExecutableKernelNode 2y ~ } N JbKb5 TbB C D z J
1721 elif isinstance(node, MemsetNode): 2U Y u Z 0 K Q M V W G H I E F Lb1 R a b 2 P
1722 view_type = ExecutableMemsetNode 10EF
1723 elif isinstance(node, MemcpyNode): 2U Y u Z K Q M V W G H I Lb1 R a b 2 P
1724 view_type = ExecutableMemcpyNode 1uZGHIab
1725 elif isinstance(node, ChildGraphNode): 2U Y K Q M V W Lb1 R 2 P
1726 view_type = ExecutableChildGraphNode 1UK
1727 elif isinstance(node, EventRecordNode): 2Y Q M V W Lb1 R 2 P
1728 view_type = ExecutableEventRecordNode 1Q
1729 elif isinstance(node, EventWaitNode): 2Y M V W Lb1 R 2 P
1730 view_type = ExecutableEventWaitNode 1M
1731 elif isinstance(node, HostCallbackNode): 2Y V W Lb1 R 2 P
1732 view_type = ExecutableHostCallbackNode 1YVW1R2P
1733 else:
1734 raise TypeError( 2Lb
1735 f"{type(node).__name__} does not support executable updates") 2Lb
1737 if as_cu(h_exec) == NULL: 2U y Y ~ } N JbKbu 5 Z 0 TbK Q M V W B C D G H I E F 1 R z a b J 2 P
1738 raise ValueError("executable graph has been closed")
1739 if as_cu(node._h_node) == NULL: 2U y Y ~ } N JbKbu 5 Z 0 TbK Q M V W B C D G H I E F 1 R z a b J 2 P
1740 raise ValueError("source graph node is no longer valid")
1742 cdef ExecutableGraphNode view = view_type.__new__(view_type) 2U y Y ~ } N JbKbu 5 Z 0 TbK Q M V W B C D G H I E F 1 R z a b J 2 P
1743 view._h_graph_exec = h_exec 2U y Y ~ } N JbKbu 5 Z 0 TbK Q M V W B C D G H I E F 1 R z a b J 2 P
1744 view._h_node = node._h_node 2U y Y ~ } N JbKbu 5 Z 0 TbK Q M V W B C D G H I E F 1 R z a b J 2 P
1745 return view 2U y Y ~ } N JbKbu 5 Z 0 TbK Q M V W B C D G H I E F 1 R z a b J 2 P