Coverage for cuda/core/graph/_graph_builder.pyx: 78.08%

520 statements  

« prev     ^ index     » next       coverage.py v7.17.2, created at 2026-11-05 01:11 +0000

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

2# 

3# SPDX-License-Identifier: Apache-2.0 

4  

5from dataclasses import dataclass 

6from typing import TYPE_CHECKING 

7  

8from libc.stdint cimport intptr_t 

9  

10from cuda.bindings cimport cydriver 

11  

12from cuda.core.graph._graph_definition cimport ( 

13 GraphCondition, 

14 GraphDefinition, 

15 GD_check_valid, 

16) 

17from cuda.core.graph._graph_node cimport GraphNode, GN_check_valid 

18from cuda.core._host_callback cimport _resolve_host_callback 

19from cuda.core.graph._subclasses cimport ( 

20 ChildGraphNode, 

21 EventRecordNode, 

22 EventWaitNode, 

23 ExecutableChildGraphNode, 

24 ExecutableEventRecordNode, 

25 ExecutableEventWaitNode, 

26 ExecutableGraphNode, 

27 ExecutableHostCallbackNode, 

28 ExecutableKernelNode, 

29 ExecutableMemcpyNode, 

30 ExecutableMemsetNode, 

31 HostCallbackNode, 

32 KernelNode, 

33 MemcpyNode, 

34 MemsetNode, 

35 create_executable_node_view, 

36) 

37from cuda.core._rt cimport attach_rollback_failure, report_cuda_error 

38from cuda.core._rt cimport ( 

39 GraphExecHandle, 

40 GraphHandle, 

41 OpaqueHandle, 

42 PreparedAttachment, 

43 as_cu, as_py, 

44 create_child_graph_handle, create_graph_exec_handle, create_graph_handle, 

45 get_last_error, 

46 graph_clone_attachments, 

47 graph_commit_attachment, 

48 graph_exec_update, 

49 graph_prepare_attachment, 

50 invalidate_child_graph_state, 

51 invalidate_root_graph_state, 

52 retry_deferred_cleanup, 

53) 

54from cuda.core._stream cimport Stream, Stream_accept 

55from cuda.core._utils.cuda_utils cimport HANDLE_RETURN 

56from cuda.core._utils.version cimport cy_driver_version 

57  

58from cuda.core._utils.cuda_utils import ( 

59 CUDAError, 

60 driver, 

61 handle_return, 

62) 

63  

64if TYPE_CHECKING: 

65 from collections.abc import Callable 

66 from typing import overload 

67  

68 from cuda.core._utils.pycompat import BufferProtocol 

69  

70 from cuda.core.graph._graph_definition import GraphDefinition 

71else: 

72 # Cython applies a method decorator by rebinding the type's dict entry, so 

73 # typing.overload would replace the compiled ``__getitem__`` slot wrapper 

74 # with its placeholder. The overloads only serve the stub; at run time the 

75 # decorator must leave the method alone. 

76 def overload(f): 

77 return f 

78  

79# Each ``@overload`` stub of ``Graph.__getitem__`` still compiles to a static 

80# wrapper function that nothing references, because only the final definition 

81# is bound. gcc and clang report those under -Wunused-function, so this file 

82# turns that warning off for its own translation unit. The guard keeps the 

83# pragma away from MSVC, whose equivalent warning is off at the default level. 

84cdef extern from *: 

85 """ 

86 #if defined(__GNUC__) 

87 #pragma GCC diagnostic ignored "-Wunused-function" 

88 #endif 

89 """ 

90  

91__all__ = ['Graph', 'GraphBuilder', 'GraphCompleteOptions', 'GraphDebugPrintOptions'] 

92  

93  

94@dataclass 

95class GraphDebugPrintOptions: 

96 """Options for debug_dot_print(). 

97  

98 Attributes 

99 ---------- 

100 verbose : bool 

101 Output all debug data as if every debug flag is enabled (Default to False) 

102 runtime_types : bool 

103 Use CUDA Runtime structures for output (Default to False) 

104 kernel_node_params : bool 

105 Adds kernel parameter values to output (Default to False) 

106 memcpy_node_params : bool 

107 Adds memcpy parameter values to output (Default to False) 

108 memset_node_params : bool 

109 Adds memset parameter values to output (Default to False) 

110 host_node_params : bool 

111 Adds host parameter values to output (Default to False) 

112 event_node_params : bool 

113 Adds event parameter values to output (Default to False) 

114 ext_semas_signal_node_params : bool 

115 Adds external semaphore signal parameter values to output (Default to False) 

116 ext_semas_wait_node_params : bool 

117 Adds external semaphore wait parameter values to output (Default to False) 

118 kernel_node_attributes : bool 

119 Adds kernel node attributes to output (Default to False) 

120 handles : bool 

121 Adds node handles and every kernel function handle to output (Default to False) 

122 mem_alloc_node_params : bool 

123 Adds memory alloc parameter values to output (Default to False) 

124 mem_free_node_params : bool 

125 Adds memory free parameter values to output (Default to False) 

126 batch_mem_op_node_params : bool 

127 Adds batch mem op parameter values to output (Default to False) 

128 extra_topo_info : bool 

129 Adds edge numbering information (Default to False) 

130 conditional_node_params : bool 

131 Adds conditional node parameter values to output (Default to False) 

132  

133 """ 

134  

135 verbose: bool = False 

136 runtime_types: bool = False 

137 kernel_node_params: bool = False 

138 memcpy_node_params: bool = False 

139 memset_node_params: bool = False 

140 host_node_params: bool = False 

141 event_node_params: bool = False 

142 ext_semas_signal_node_params: bool = False 

143 ext_semas_wait_node_params: bool = False 

144 kernel_node_attributes: bool = False 

145 handles: bool = False 

146 mem_alloc_node_params: bool = False 

147 mem_free_node_params: bool = False 

148 batch_mem_op_node_params: bool = False 

149 extra_topo_info: bool = False 

150 conditional_node_params: bool = False 

151  

152 def _to_flags(self) -> int: 

153 """Convert options to CUDA driver API flags (internal use).""" 

154 flags = 0 2jda

155 if self.verbose: 2jda

156 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_VERBOSE 2jda

157 if self.runtime_types: 2jda

158 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_RUNTIME_TYPES 1a

159 if self.kernel_node_params: 2jda

160 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_KERNEL_NODE_PARAMS 1a

161 if self.memcpy_node_params: 2jda

162 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_MEMCPY_NODE_PARAMS 1a

163 if self.memset_node_params: 2jda

164 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_MEMSET_NODE_PARAMS 1a

165 if self.host_node_params: 2jda

166 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_HOST_NODE_PARAMS 1a

167 if self.event_node_params: 2jda

168 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_EVENT_NODE_PARAMS 1a

169 if self.ext_semas_signal_node_params: 2jda

170 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_EXT_SEMAS_SIGNAL_NODE_PARAMS 1a

171 if self.ext_semas_wait_node_params: 2jda

172 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_EXT_SEMAS_WAIT_NODE_PARAMS 1a

173 if self.kernel_node_attributes: 2jda

174 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_KERNEL_NODE_ATTRIBUTES 1a

175 if self.handles: 2jda

176 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_HANDLES 2jda

177 if self.mem_alloc_node_params: 2jda

178 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_MEM_ALLOC_NODE_PARAMS 1a

179 if self.mem_free_node_params: 2jda

180 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_MEM_FREE_NODE_PARAMS 1a

181 if self.batch_mem_op_node_params: 2jda

182 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_BATCH_MEM_OP_NODE_PARAMS 1a

183 if self.extra_topo_info: 2jda

184 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_EXTRA_TOPO_INFO 1a

185 if self.conditional_node_params: 2jda

186 flags |= driver.CUgraphDebugDot_flags.CU_GRAPH_DEBUG_DOT_FLAGS_CONDITIONAL_NODE_PARAMS 1a

187 return flags 2jda

188  

189  

190@dataclass 

191class GraphCompleteOptions: 

192 """Options for graph instantiation. 

193  

194 Attributes 

195 ---------- 

196 auto_free_on_launch : bool, optional 

197 Automatically free memory allocated in a graph before relaunching. (Default to False) 

198 upload_stream : Stream, optional 

199 Stream to use to automatically upload the graph after completion. (Default to None) 

200 device_launch : bool, optional 

201 Configure the graph to be launchable from the device. This flag can only 

202 be used on platforms which support unified addressing. This flag cannot be 

203 used in conjunction with auto_free_on_launch. (Default to False) 

204 use_node_priority : bool, optional 

205 Run the graph using the per-node priority attributes rather than the 

206 priority of the stream it is launched into. (Default to False) 

207  

208 """ 

209  

210 auto_free_on_launch: bool = False 

211 upload_stream: Stream | None = None 

212 device_launch: bool = False 

213 use_node_priority: bool = False 

214  

215  

216def _instantiate_graph(source, options: GraphCompleteOptions | None = None) -> Graph: 

217 cdef GraphHandle h_graph 

218 cdef GraphExecHandle h_exec 

219 cdef cydriver.CUresult status 

220  

221 if isinstance(source, GraphBuilder): 2P nbF L M N O cbH : x z 3 y odG ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~bfb* @ K I ~ [

222 GB_check_open(<GraphBuilder>source) 2P F L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E | ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( w 1 ) ? ] fb* @ K I ~ [

223 h_graph = (<GraphBuilder>source)._h_graph 2P F L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E | ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( w 1 ) ? ] fb* @ K I ~ [

224 elif isinstance(source, GraphDefinition): 2nbod+b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTcac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7b(b)b}b~b

225 GD_check_valid(<GraphDefinition>source) 2nbod+b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTcac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7b(b)b}b~b

226 h_graph = (<GraphDefinition>source)._h_graph 2nbod+b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTcac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7b(b)b}b~b

227 else: 

228 raise TypeError( 

229 f"expected GraphBuilder or GraphDefinition, got {type(source).__name__}") 

230  

231 cdef cydriver.CUDA_GRAPH_INSTANTIATE_PARAMS params = cydriver.CUDA_GRAPH_INSTANTIATE_PARAMS( 2P nbF L M N O cbH : x z 3 y odG ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~bfb* @ K I ~ [

232 flags=0, 

233 hUploadStream=<cydriver.CUstream>NULL, 2P nbF L M N O cbH : x z 3 y odG ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~bfb* @ K I ~ [

234 hErrNode_out=<cydriver.CUgraphNode>NULL, 2P nbF L M N O cbH : x z 3 y odG ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~bfb* @ K I ~ [

235 result_out=cydriver.CUgraphInstantiateResult.CUDA_GRAPH_INSTANTIATE_SUCCESS, 2P nbF L M N O cbH : x z 3 y odG ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~bfb* @ K I ~ [

236 ) 

237 if options: 2P nbF L M N O cbH : x z 3 y odG ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~bfb* @ K I ~ [

238 flags = 0 2odSbTb#bUbVb$bWbXbYb%bZb0b'bwcxcfd5b0 V W fb*

239 if options.auto_free_on_launch: 2odSbTb#bUbVb$bWbXbYb%bZb0b'bwcxcfd5b0 V W fb*

240 flags |= driver.CUgraphInstantiate_flags.CUDA_GRAPH_INSTANTIATE_FLAG_AUTO_FREE_ON_LAUNCH 2SbUbXbZbwcxc0 V W fb*

241 if options.upload_stream is not None: 2odSbTb#bUbVb$bWbXbYb%bZb0b'bwcxcfd5b0 V W fb*

242 flags |= driver.CUgraphInstantiate_flags.CUDA_GRAPH_INSTANTIATE_FLAG_UPLOAD 2od#b$b%b'b*

243 params.hUploadStream = as_cu(Stream_accept(options.upload_stream)._h_stream) 2od#b$b%b'b*

244 if options.device_launch: 2SbTb#bUbVb$bWbXbYb%bZb0b'bwcxcfd5b0 V W fb*

245 flags |= driver.CUgraphInstantiate_flags.CUDA_GRAPH_INSTANTIATE_FLAG_DEVICE_LAUNCH 2Wbfd5bfb*

246 if options.use_node_priority: 2SbTb#bUbVb$bWbXbYb%bZb0b'bwcxcfd5b0 V W fb*

247 flags |= driver.CUgraphInstantiate_flags.CUDA_GRAPH_INSTANTIATE_FLAG_USE_NODE_PRIORITY 2TbVbYb0bwcxc*

248 params.flags = flags 2SbTb#bUbVb$bWbXbYb%bZb0b'bwcxcfd5b0 V W fb*

249  

250 # The exec is adopted only when result_out reports success, so the 

251 # diagnostics below run before the handle is checked. 

252 h_exec = create_graph_exec_handle(h_graph, &params) 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~bfb* @ K I ~ [

253 status = get_last_error() 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~bfb* @ K I ~ [

254 if params.result_out == driver.CUgraphInstantiateResult.CUDA_GRAPH_INSTANTIATE_ERROR: 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~bfb* @ K I ~ [

255 # HANDLE_RETURN raises CUDAError with the CUresult name and message (e.g. CUDA_ERROR_INVALID_VALUE) 

256 # when status is not CUDA_SUCCESS. 

257 HANDLE_RETURN(status) 2fb

258 raise RuntimeError( 

259 "CUDA graph instantiation failed, but cuGraphInstantiateWithParams " 

260 "returned CUDA_SUCCESS; no driver error details are available." 

261 ) 

262 elif params.result_out == driver.CUgraphInstantiateResult.CUDA_GRAPH_INSTANTIATE_INVALID_STRUCTURE: 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b* @ K I ~ [

263 raise RuntimeError("Instantiation failed due to invalid structure, such as cycles.") 2sc

264 elif params.result_out == driver.CUgraphInstantiateResult.CUDA_GRAPH_INSTANTIATE_NODE_OPERATION_NOT_SUPPORTED: 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcddedfd5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b* @ K I ~ [

265 raise RuntimeError( 2fd

266 "Instantiation for device launch failed because the graph contained an unsupported operation." 

267 ) 

268 elif params.result_out == driver.CUgraphInstantiateResult.CUDA_GRAPH_INSTANTIATE_MULTIPLE_CTXS_NOT_SUPPORTED: 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcdded5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b* @ K I ~ [

269 raise RuntimeError("Instantiation for device launch failed due to the nodes belonging to different contexts.") 25b

270 elif params.result_out == driver.CUgraphInstantiateResult.CUDA_GRAPH_INSTANTIATE_CONDITIONAL_HANDLE_UNUSED: 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcdded5bscmdgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b* @ K I ~ [

271 raise RuntimeError("One or more conditional handles are not associated with conditional builders.") 2md

272 elif params.result_out != driver.CUgraphInstantiateResult.CUDA_GRAPH_INSTANTIATE_SUCCESS: 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcdded5bscgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b* @ K I ~ [

273 raise RuntimeError(f"Graph instantiation failed with unexpected error code: {params.result_out}") 

274  

275 if as_cu(h_exec) == NULL: 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcdded5bscgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b* @ K I ~ [

276 HANDLE_RETURN(status) 

277 return Graph._init(h_exec) 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcdded5bscgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b* @ K I ~ [

278  

279  

280# Distinguishes the three kinds of GraphBuilder, which differ in how they 

281# begin/end stream capture and whether they own the resulting CUgraph. 

282# Each kind progresses through _CaptureState as follows: 

283# 

284# PRIMARY: NOT_STARTED -> CAPTURING -> ENDED | INVALIDATED 

285# FORKED: CAPTURING (never transitions; joined and closed) 

286# CONDITIONAL_BODY: NOT_STARTED -> CAPTURING -> ENDED | INVALIDATED 

287# 

288cdef enum _BuilderKind: 

289 # PRIMARY: The top-level builder created by Device or Stream. Owns the 

290 # captured CUgraph via an owning GraphHandle. Progresses through all three 

291 # capture states; responsible for ending capture if destroyed early. When 

292 # the capture ends invalidated, the driver discards the graph and the 

293 # handle is dropped without destroying it (see GB_end_capture). 

294 PRIMARY = 0 

295 # FORKED: Created by split(). Captures on a private stream forked from the 

296 # primary. Starts in CAPTURING state and never transitions; the user joins 

297 # it back to the primary via join(), which closes the builder. Must NOT 

298 # call cuStreamEndCapture (the driver requires all forked streams to be 

299 # joined first). 

300 FORKED = 1 

301 # CONDITIONAL_BODY: Created by if_then/if_else/switch/while_loop. Captures 

302 # into a non-owned body graph via cuStreamBeginCaptureToGraph. The body 

303 # graph's lifetime is tied to a parent graph. Progresses through all three 

304 # capture states like PRIMARY. 

305 CONDITIONAL_BODY = 2 

306  

307  

308# Tracks the capture lifecycle of a GraphBuilder. 

309cdef enum _CaptureState: 

310 CAPTURE_NOT_STARTED = 0 

311 CAPTURING = 1 

312 CAPTURE_ENDED = 2 # Finished, valid handle 

313 CLOSED = 3 # No valid handle 

314 CAPTURE_INVALIDATED = 4 # Ended in error; the driver discarded the graph 

315  

316  

317cdef class GraphBuilder: 

318 """A graph under construction by stream capture. 

319  

320 A graph groups a set of CUDA kernels and other CUDA operations together and executes 

321 them with a specified dependency tree. It speeds up the workflow by combining the 

322 driver activities associated with CUDA kernel launches and CUDA API calls. 

323  

324 Directly creating a :obj:`~graph.GraphBuilder` is not supported due 

325 to ambiguity. New graph builders should instead be created through a 

326 :obj:`~_device.Device`, or a :obj:`~_stream.stream` object. 

327  

328 .. note:: 

329  

330 Operations recorded during capture reference your memory but do not 

331 take ownership of it. As with ordinary stream work, you must keep the 

332 operands alive for as long as the completed graph may execute -- for 

333 example, the :obj:`~_memory.Buffer` objects passed to :func:`~launch` 

334 or :meth:`~_memory.Buffer.copy_to`. Host callbacks added with 

335 :meth:`callback` are the exception: the callable (and any copied 

336 ``user_data``) are retained for the graph's lifetime. This differs from 

337 building a graph explicitly with :class:`~graph.GraphDefinition`, which 

338 retains the operands it is given. 

339  

340 """ 

341  

342 def __init__(self): 

343 raise NotImplementedError( 2qd

344 "directly creating a GraphBuilder object can be ambiguous. Please either " 

345 "call Device.create_graph_builder() or stream.create_graph_builder()" 

346 ) 

347  

348 def __dealloc__(self): 

349 cdef cydriver.CUresult err = GB_end_capture(self) 2`c~cP Cbnb9bidpbobF lbibjbnd1bqdqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

350 if err != cydriver.CUDA_SUCCESS: 2`c~cP Cbnb9bidpbobF lbibjbnd1bqdqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

351 # Nothing can be raised from __dealloc__: report instead. 

352 report_cuda_error( 29b

353 b"cuStreamEndCapture", err, 

354 b"failed while releasing a GraphBuilder that was still building") 

355  

356 @staticmethod 

357 def _init(Stream stream): 

358 cdef GraphBuilder self = GraphBuilder.__new__(GraphBuilder) 2`c~cP Cbnb9bidpbobF lbibjbnd1bqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

359 # _h_graph set by begin_building 

360 self._h_stream = stream._h_stream 2`c~cP Cbnb9bidpbobF lbibjbnd1bqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

361 self._kind = PRIMARY 2`c~cP Cbnb9bidpbobF lbibjbnd1bqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

362 self._state = CAPTURE_NOT_STARTED 2`c~cP Cbnb9bidpbobF lbibjbnd1bqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

363 self._stream = stream 2`c~cP Cbnb9bidpbobF lbibjbnd1bqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

364 return self 2`c~cP Cbnb9bidpbobF lbibjbnd1bqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

365  

366 def close(self): 

367 """Destroy the graph builder. 

368  

369 A builder that is still building ends its capture first. The builder 

370 is closed even when that fails; the driver error is raised afterwards. 

371 """ 

372 HANDLE_RETURN(GB_close(self)) 2`cCbnbF lbibjbqb: # rbZ mby G T U = 6 b c d e f g h i j k l m n o p q r s t u v a tbAbubvb{c|ckdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c

373  

374 @property 

375 def is_closed(self) -> bool: 

376 """Whether this graph builder has been closed.""" 

377 return self._state == CLOSED 2CbnbT U }c

378  

379 @property 

380 def stream(self) -> Stream: 

381 """Returns the stream associated with the graph builder.""" 

382 GB_check_open(self) 2`cF qbH : # x z rbZ sb3 mby *bG T U ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E gbabdbhbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbubvb@ {c|c~ wbxbyb}c[

383 return self._stream 2`cF qbH : # x z rbZ sb3 mby *bG T U ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E gbabdbhbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbubvb@ {c|c~ wbxbyb[

384  

385 @property 

386 def is_join_required(self) -> bool: 

387 """Returns True if this graph builder must be joined before building is ended.""" 

388 return self._kind == FORKED 1F#ZyGTUbcdefghijklmnopqrstuva

389  

390 @property 

391 def graph_definition(self) -> GraphDefinition: 

392 """The captured graph as an explicit :class:`~graph.GraphDefinition`. 

393  

394 .. versionadded:: 1.1.0 

395  

396 The returned :class:`~graph.GraphDefinition` is a view of the same 

397 graph this builder is producing: nodes added through it appear in 

398 subsequent :meth:`complete` and :meth:`debug_dot_print` calls, and 

399 the view stays valid even after the builder is closed. 

400  

401 This lets you mix the capture and explicit APIs on a single graph, 

402 for example to inspect what was captured, augment it with extra 

403 nodes, or build a conditional body entirely with the explicit API. 

404  

405 Availability: 

406  

407 - **Primary builders** (created by :meth:`Device.create_graph_builder` 

408 or :meth:`Stream.create_graph_builder`): only after 

409 :meth:`end_building`. 

410  

411 - **Conditional-body builders** (returned by :meth:`if_then`, 

412 :meth:`if_else`, :meth:`while_loop`, :meth:`switch`): both before 

413 :meth:`begin_building` and after :meth:`end_building`. The body 

414 graph already exists when the conditional is created, so you may 

415 populate it through this view without ever calling 

416 :meth:`begin_building` on the body builder. 

417  

418 - **Forked builders** (returned by :meth:`split`): never. Forked 

419 builders share the primary builder's graph; access it through the 

420 primary instead. 

421  

422 Returns 

423 ------- 

424 GraphDefinition 

425 A view of the graph being built. 

426  

427 Raises 

428 ------ 

429 RuntimeError 

430 If the builder is closed, forked, currently building, or (for 

431 primary builders) has not started building yet. A 

432 :class:`~graph.GraphDefinition` obtained before :meth:`close` 

433 keeps working; only fresh access through this property is 

434 rejected once the builder is closed. 

435 """ 

436 GB_check_open(self) 2lbibjbx S z rbadQbZ sb3 mb4 J 2 R Q X Y /

437 if self._kind == FORKED: 2lbibjbx S z adQbZ sb3 mb4 J 2 R Q X Y /

438 raise RuntimeError( 1Z

439 "graph_definition is unavailable on forked graph builders; " 

440 "access it through the primary builder instead." 

441 ) 

442 elif self._state == CAPTURING: 2lbibjbx S z adQbsb3 mb4 J 2 R Q X Y /

443 raise RuntimeError( 2S Qb

444 "graph_definition is unavailable while capture is in " 

445 "progress; call end_building() first." 

446 ) 

447 GB_check_has_graph(self) 2lbibjbx z adsb3 mb4 J 2 R Q X Y /

448 if self._kind == PRIMARY: 2x z adsb3 mb4 J 2 R Q X Y /

449 if self._state == CAPTURE_NOT_STARTED: 2adsb3 mb4 J 2 R Q X Y /

450 raise RuntimeError( 2ad

451 "graph_definition is unavailable before begin_building() on " 

452 "a primary builder; no graph has been created yet." 

453 ) 

454 return GraphDefinition._from_handle(self._h_graph) 2x z sb3 mb4 J 2 R Q X Y /

455  

456 def begin_building(self, mode: str | None = "relaxed") -> GraphBuilder: 

457 """Begins the building process. 

458  

459 Build `mode` for controlling interaction with other API calls must be one of the following: 

460  

461 - `global` : Prohibit potentially unsafe operations across all streams in the process. 

462 - `thread_local` : Prohibit potentially unsafe operations in streams created by the current thread. 

463 - `relaxed` : The local thread is not prohibited from potentially unsafe operations. 

464  

465 Parameters 

466 ---------- 

467 mode : str, optional 

468 Build mode to control the interaction with other API calls that are porentially unsafe. 

469 Default set to use relaxed. 

470  

471 """ 

472 GB_check_open(self) 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

473 if self._state != CAPTURE_NOT_STARTED: 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

474 if self._state == CAPTURING: 21b;

475 raise RuntimeError("Graph builder is already building.") 21b

476 else: 

477 raise RuntimeError("Cannot resume building after building has ended.") 1;

478 cdef cydriver.CUstreamCaptureMode c_mode 

479 if mode == "global": 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

480 c_mode = cydriver.CU_STREAM_CAPTURE_MODE_GLOBAL 2lb| gb!b} hb+ , 0 - . PbIbJbKbLbMbNbOb

481 elif mode == "thread_local": 2P Cb9bpbobF ibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J ^ ` abdb8b_ { bbeb7 $ 8 % V W 9 ' ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ EbFbGbHbwbxbybBb[

482 c_mode = cydriver.CU_STREAM_CAPTURE_MODE_THREAD_LOCAL 2jb` db8b{ eb$ % W ' ( PbEbFbGbHb

483 elif mode == "relaxed": 2P Cb9bpbobF ib1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J ^ ab_ bb7 8 V 9 ! 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ wbxbybBb[

484 c_mode = cydriver.CU_STREAM_CAPTURE_MODE_RELAXED 2P Cb9bpbobF ib1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J ^ ab_ bb7 8 V 9 ! 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ wbxbybBb[

485 else: 

486 raise ValueError(f"Unsupported build mode: {mode}") 2Pb

487  

488 cdef cydriver.CUstream c_stream = as_cu(self._h_stream) 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

489 cdef cydriver.CUgraph c_graph 

490 cdef cydriver.CUstreamCaptureStatus c_status 

491 if self._kind == CONDITIONAL_BODY: 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

492 c_graph = as_cu(self._h_graph) 1xSbcdefghijklmnopqArstuvBCDEwa

493 with nogil: 1xSbcdefghijklmnopqArstuvBCDEwa

494 HANDLE_RETURN(cydriver.cuStreamBeginCaptureToGraph( 1xSbcdefghijklmnopqArstuvBCDEwa

495 c_stream, c_graph, NULL, NULL, 0, c_mode)) 

496 self._state = CAPTURING 1xSbcdefghijklmnopqArstuvBCDEwa

497 else: 

498 with nogil: 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

499 HANDLE_RETURN(cydriver.cuStreamBeginCapture(c_stream, c_mode)) 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

500 # Capture is active now; set CAPTURING before the calls below so a 

501 # failure in _get_capture_info/create_graph_handle still lets 

502 # cleanup end the capture rather than leaving the stream poisoned. 

503 self._state = CAPTURING 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

504 with nogil: 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

505 # The driver rejects a NULL captureStatus_out, so pass a 

506 # stack-local even though we only want the graph handle. 

507 _get_capture_info(c_stream, &c_status, &c_graph) 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

508 self._h_graph = create_graph_handle(c_graph) 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

509 return self 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

510  

511 @property 

512 def is_building(self) -> bool: 

513 """Returns True if the graph builder is currently building.""" 

514 GB_check_open(self) 2oblbibjbqbH DbJ | ^ ` } _ {

515 cdef cydriver.CUstream c_stream = as_cu(self._h_stream) 2oblbibjbqbH DbJ | ^ ` } _ {

516 cdef cydriver.CUstreamCaptureStatus status 

517 with nogil: 2oblbibjbqbH DbJ | ^ ` } _ {

518 _get_capture_info(c_stream, &status, NULL) 2oblbibjbqbH DbJ | ^ ` } _ {

519 if status == cydriver.CU_STREAM_CAPTURE_STATUS_NONE: 2oblbibjbqbH DbJ | ^ ` } _ {

520 return False 2oblbibjbDb

521 elif status == cydriver.CU_STREAM_CAPTURE_STATUS_ACTIVE: 

522 return True 2qbH DbJ | ^ ` } _ {

523 elif status == cydriver.CU_STREAM_CAPTURE_STATUS_INVALIDATED: 

524 raise RuntimeError( 2lbibjb

525 "Build process encountered an error and has been invalidated. " 

526 "Call end_building() to end it; the error is raised there." 

527 ) 

528 else: 

529 raise NotImplementedError(f"Unsupported capture status type received: {status}") 

530  

531 def end_building(self) -> GraphBuilder: 

532 """Ends the building process. 

533  

534 Raises 

535 ------ 

536 RuntimeError 

537 If the builder is not building. A forked builder is ended by 

538 :meth:`join`, not by this method. 

539 CUDAError 

540 If the capture was invalidated, for example by a CUDA call that is 

541 not permitted while capturing. The capture is ended and the 

542 builder holds no graph afterwards, so :meth:`complete` and 

543 :attr:`graph_definition` are unavailable. This applies to a 

544 top-level builder. An invalidated capture of a conditional body 

545 leaves the parent builder's graph invalid as well; ending it may 

546 crash the process (see issue #2918). 

547 """ 

548 GB_check_open(self) 2P pbobF lbibjbnd1bzbL M N O cbH : x S z rbQbZ sb3 mb4by DbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

549 if self._state != CAPTURING: 2P pbobF lbibjbnd1bzbL M N O cbH : x S z rbQbZ sb3 mb4by DbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

550 raise RuntimeError("Graph builder is not building.") 2nd

551 if self._kind == FORKED: 2P pbobF lbibjb1bzbL M N O cbH : x S z rbQbZ sb3 mb4by DbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

552 raise RuntimeError( 1F

553 "A forked graph builder is ended by GraphBuilder.join(), not end_building().") 

554 HANDLE_RETURN(GB_end_capture(self)) 2P pbobF lbibjb1bzbL M N O cbH : x S z rbQbZ sb3 mb4by DbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

555  

556 # TODO: Resolving https://github.com/NVIDIA/cuda-python/issues/617 would allow us to 

557 # resume the build process after the first call to end_building() 

558 return self 2P pbobF 1bzbL M N O cbH : x S z rbQbZ sb3 mb4by DbG ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

559  

560 def complete(self, options: GraphCompleteOptions | None = None) -> Graph: 

561 """Completes the graph builder and returns the built :obj:`~graph.Graph` object. 

562  

563 Parameters 

564 ---------- 

565 options : :obj:`~graph.GraphCompleteOptions`, optional 

566 Customizable dataclass for the graph builder completion options. 

567  

568 Returns 

569 ------- 

570 graph : :obj:`~graph.Graph` 

571 The newly built graph. 

572  

573 """ 

574 GB_check_open(self) 2P F lbibjbL M N O cbH : # x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E | ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( w 1 ) ? ] fb* @ K I ~ [

575 GB_check_has_graph(self) 2P F lbibjbL M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E | ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( w 1 ) ? ] fb* @ K I ~ [

576 if self._state != CAPTURE_ENDED: 2P F L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E | ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( w 1 ) ? ] fb* @ K I ~ [

577 raise RuntimeError("Graph has not finished building.") 2cb

578  

579 return _instantiate_graph(self, options) 2P F L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E | ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( w 1 ) ? ] fb* @ K I ~ [

580  

581 def debug_dot_print(self, path: str, options: GraphDebugPrintOptions | None = None) -> None: 

582 """Generates a DOT debug file for the graph builder. 

583  

584 Parameters 

585 ---------- 

586 path : str 

587 File path to use for writting debug DOT output 

588 options : :obj:`~graph.GraphDebugPrintOptions`, optional 

589 Customizable dataclass for the debug print options. 

590  

591 """ 

592 GB_check_open(self) 2pba

593 GB_check_has_graph(self) 2pba

594 if self._state != CAPTURE_ENDED: 2pba

595 raise RuntimeError("Graph has not finished building.") 2pb

596 cdef unsigned int c_flags = options._to_flags() if options else 0 2pba

597 cdef cydriver.CUgraph c_graph = as_cu(self._h_graph) 2pba

598 cdef bytes b_path = path.encode('utf-8') 2pba

599 cdef const char* c_path = b_path 2pba

600 with nogil: 2pba

601 HANDLE_RETURN(cydriver.cuGraphDebugDotPrint(c_graph, c_path, c_flags)) 2pba

602  

603 def split(self, count: int) -> tuple[GraphBuilder, ...]: 

604 """Splits the original graph builder into multiple graph builders. 

605  

606 The new builders inherit work dependencies from the original builder. 

607 The original builder is reused for the split and is returned first in the tuple. 

608  

609 Parameters 

610 ---------- 

611 count : int 

612 The number of graph builders to split the graph builder into. 

613  

614 Returns 

615 ------- 

616 graph_builders : tuple[:obj:`~graph.GraphBuilder`, ...] 

617 A tuple of split graph builders. The first graph builder in the tuple 

618 is always the original graph builder. 

619  

620 """ 

621 if count < 2: 2F # Z y G T U ldb c d e f g h i j k l m n o p q r s t u v a

622 raise ValueError(f"Invalid split count: expecting >= 2, got {count}") 1y

623 GB_check_open(self) 2F # Z y G T U ldb c d e f g h i j k l m n o p q r s t u v a

624 if self._state != CAPTURING: 2F # Z y G T U ldb c d e f g h i j k l m n o p q r s t u v a

625 raise RuntimeError("Graph builder must be building before it can be split.") 2ld

626  

627 event = self._stream.record() 1F#ZyGTUbcdefghijklmnopqrstuva

628 result = [self] 1F#ZyGTUbcdefghijklmnopqrstuva

629 for _ in range(count - 1): 1F#ZyGTUbcdefghijklmnopqrstuva

630 stream = self._stream.device.create_stream() 1F#ZyGTUbcdefghijklmnopqrstuva

631 stream.wait(event) 1F#ZyGTUbcdefghijklmnopqrstuva

632 result.append(GB_init_forked(stream, self._h_graph)) 1F#ZyGTUbcdefghijklmnopqrstuva

633 event.close() 1F#ZyGTUbcdefghijklmnopqrstuva

634 return tuple(result) 1F#ZyGTUbcdefghijklmnopqrstuva

635  

636 @staticmethod 

637 def join(*graph_builders: GraphBuilder) -> GraphBuilder: 

638 """Joins multiple graph builders into a single graph builder. 

639  

640 The returned builder inherits work dependencies from the provided builders. 

641 If joining fails partway, the builders that were not joined are closed 

642 before the error propagates, so none is left capturing. A driver error 

643 from one of those closes is attached to the propagating error as a note. 

644  

645 Parameters 

646 ---------- 

647 *graph_builders : :obj:`~graph.GraphBuilder` 

648 The graph builders to join. 

649  

650 Returns 

651 ------- 

652 graph_builder : :obj:`~graph.GraphBuilder` 

653 The newly joined graph builder. 

654  

655 """ 

656 if any(not isinstance(builder, GraphBuilder) for builder in graph_builders): 2nbF # Z y G T U pdb c d e f g h i j k l m n o p q r s t u v a

657 raise TypeError("All arguments must be GraphBuilder instances") 2pd

658 if len(graph_builders) < 2: 2nbF # Z y G T U b c d e f g h i j k l m n o p q r s t u v a

659 raise ValueError("Must join with at least two graph builders") 1y

660 for builder in graph_builders: 2nbF # Z y G T U b c d e f g h i j k l m n o p q r s t u v a

661 GB_check_open(builder) 2nbF # Z y G T U b c d e f g h i j k l m n o p q r s t u v a

662  

663 # Discover the root builder others should join 

664 root_idx = 0 1F#ZyGTUbcdefghijklmnopqrstuva

665 for i, builder in enumerate(graph_builders): 1F#ZyGTUbcdefghijklmnopqrstuva

666 if not builder.is_join_required: 1F#ZyGTUbcdefghijklmnopqrstuva

667 root_idx = i 1F#ZyGTUbcdefghijklmnopqrstuva

668 break 1F#ZyGTUbcdefghijklmnopqrstuva

669  

670 # Join all onto the root builder 

671 root_bdr = graph_builders[root_idx] 1F#ZyGTUbcdefghijklmnopqrstuva

672 cdef GraphBuilder unjoined 

673 try: 1F#ZyGTUbcdefghijklmnopqrstuva

674 for idx, builder in enumerate(graph_builders): 1F#ZyGTUbcdefghijklmnopqrstuva

675 if idx == root_idx: 1F#ZyGTUbcdefghijklmnopqrstuva

676 continue 1F#ZyGTUbcdefghijklmnopqrstuva

677 root_bdr.stream.wait(builder.stream) 1F#ZyGTUbcdefghijklmnopqrstuva

678 builder.close() 1F#ZyGbcdefghijklmnopqrstuva

679 except BaseException: 1TU

680 # A fork left open mid-capture crashed the interpreter when it was 

681 # collected later (#2776). Close whatever the loop did not reach. A 

682 # close that fails (a builder from another capture, which the 

683 # refused wait has invalidated) must neither stop this sweep nor 

684 # replace the error being raised, so its status is attached to 

685 # that error as a note (error handling policy). 

686 for idx, builder in enumerate(graph_builders): 1TU

687 if idx != root_idx and not builder.is_closed: 1TU

688 unjoined = builder 1TU

689 attach_rollback_failure( 1TU

690 b"cuStreamEndCapture", GB_close(unjoined), 

691 b"failed while closing a graph builder that GraphBuilder.join did not join") 

692 raise 1TU

693  

694 return root_bdr 1F#ZyGbcdefghijklmnopqrstuva

695  

696 def __cuda_stream__(self) -> tuple[int, int]: 

697 """Return an instance of a __cuda_stream__ protocol.""" 

698 GB_check_open(self) 2`c

699 return self.stream.__cuda_stream__() 2`c

700  

701 def _get_conditional_context(self) -> driver.CUcontext: 

702 return self._stream.context.handle 2x S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

703  

704 def create_condition(self, default_value: int | None = None) -> GraphCondition: 

705 """Create a condition variable for use with conditional nodes. 

706  

707 The returned :class:`GraphCondition` object is passed to conditional-node 

708 builder methods (:meth:`if_then`, :meth:`if_else`, :meth:`while_loop`, 

709 :meth:`switch`). Its value is controlled at runtime by device code via 

710 ``cudaGraphSetConditional``. 

711  

712 Parameters 

713 ---------- 

714 default_value : int, optional 

715 The default value to assign to the condition. If None, no 

716 default is assigned. 

717  

718 Returns 

719 ------- 

720 GraphCondition 

721 A condition variable for controlling conditional execution. 

722 """ 

723 GB_check_open(self) 2idx S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

724 if cy_driver_version() < (12, 3, 0): 2idx S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

725 raise RuntimeError(f"Driver version {'.'.join(map(str, cy_driver_version()))} does not support conditional handles") 

726 if default_value is not None: 2idx S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

727 flags = driver.CU_GRAPH_COND_ASSIGN_DEFAULT 2x S z kbB C D E w

728 else: 

729 default_value = 0 2idb c d e f g h i j k l m n o p q A r s t u v a

730 flags = 0 2idb c d e f g h i j k l m n o p q A r s t u v a

731  

732 status, _, graph, *_, _ = handle_return(driver.cuStreamGetCaptureInfo(self._stream.handle)) 2idx S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

733 if status != driver.CUstreamCaptureStatus.CU_STREAM_CAPTURE_STATUS_ACTIVE: 2idx S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

734 raise RuntimeError("Cannot create a condition when graph is not being built") 2id

735  

736 raw_handle = handle_return( 2x S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

737 driver.cuGraphConditionalHandleCreate(graph, self._get_conditional_context(), default_value, flags) 2x S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

738 ) 

739 return GraphCondition._from_handle(<cydriver.CUgraphConditionalHandle><intptr_t>int(raw_handle)) 2x S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

740  

741 def if_then(self, GraphCondition condition not None: GraphCondition) -> GraphBuilder: 

742 """Adds an if condition branch and returns a new graph builder for it. 

743  

744 The resulting if graph will only execute the branch if the 

745 condition evaluates to true at runtime. 

746  

747 The new builder inherits work dependencies from the original builder. 

748  

749 Parameters 

750 ---------- 

751 condition : :class:`~graph.GraphCondition` 

752 The condition variable from :meth:`create_condition` controlling 

753 whether the branch executes. 

754  

755 Returns 

756 ------- 

757 graph_builder : :obj:`~graph.GraphBuilder` 

758 The newly created conditional graph builder. 

759  

760 """ 

761 GB_check_open(self) 2x S z kbb c d e f g h i A r a

762 if cy_driver_version() < (12, 3, 0): 2x S z kbb c d e f g h i A r a

763 raise RuntimeError(f"Driver version {'.'.join(map(str, cy_driver_version()))} does not support conditional if") 

764 if not isinstance(condition, GraphCondition): 2x S z kbb c d e f g h i A r a

765 raise TypeError( 

766 f"condition must be a GraphCondition object (from " 

767 f"GraphBuilder.create_condition()), got {type(condition).__name__}") 

768 node_params = driver.CUgraphNodeParams() 2x S z kbb c d e f g h i A r a

769 node_params.type = driver.CUgraphNodeType.CU_GRAPH_NODE_TYPE_CONDITIONAL 2x S z kbb c d e f g h i A r a

770 node_params.conditional.handle = condition.handle 2x S z kbb c d e f g h i A r a

771 node_params.conditional.type = driver.CUgraphConditionalNodeType.CU_GRAPH_COND_TYPE_IF 2x S z kbb c d e f g h i A r a

772 node_params.conditional.size = 1 2x S z kbb c d e f g h i A r a

773 node_params.conditional.ctx = self._get_conditional_context() 2x S z kbb c d e f g h i A r a

774 return GB_cond_with_params(self, node_params)[0] 2x S z kbb c d e f g h i A r a

775  

776 def if_else(self, GraphCondition condition not None: GraphCondition) -> tuple[GraphBuilder, GraphBuilder]: 

777 """Adds an if-else condition branch and returns new graph builders for both branches. 

778  

779 The resulting if graph will execute the branch if the condition 

780 evaluates to true at runtime, otherwise the else branch will execute. 

781  

782 The new builders inherit work dependencies from the original builder. 

783  

784 Parameters 

785 ---------- 

786 condition : :class:`~graph.GraphCondition` 

787 The condition variable from :meth:`create_condition` controlling 

788 which branch executes. 

789  

790 Returns 

791 ------- 

792 graph_builders : tuple[:obj:`~graph.GraphBuilder`, :obj:`~graph.GraphBuilder`] 

793 A tuple of two new graph builders, one for the if branch and one for the else branch. 

794  

795 """ 

796 GB_check_open(self) 1jklmnopq

797 if cy_driver_version() < (12, 8, 0): 1jklmnopq

798 raise RuntimeError(f"Driver version {'.'.join(map(str, cy_driver_version()))} does not support conditional if-else") 

799 if not isinstance(condition, GraphCondition): 1jklmnopq

800 raise TypeError( 

801 f"condition must be a GraphCondition object (from " 

802 f"GraphBuilder.create_condition()), got {type(condition).__name__}") 

803 node_params = driver.CUgraphNodeParams() 1jklmnopq

804 node_params.type = driver.CUgraphNodeType.CU_GRAPH_NODE_TYPE_CONDITIONAL 1jklmnopq

805 node_params.conditional.handle = condition.handle 1jklmnopq

806 node_params.conditional.type = driver.CUgraphConditionalNodeType.CU_GRAPH_COND_TYPE_IF 1jklmnopq

807 node_params.conditional.size = 2 1jklmnopq

808 node_params.conditional.ctx = self._get_conditional_context() 1jklmnopq

809 return GB_cond_with_params(self, node_params) 1jklmnopq

810  

811 def switch(self, GraphCondition condition not None: GraphCondition, count: int) -> tuple[GraphBuilder, ...]: 

812 """Adds a switch condition branch and returns new graph builders for all cases. 

813  

814 The resulting switch graph will execute the branch whose case index 

815 matches the value of the condition at runtime. If no match is found, no 

816 branch will be executed. 

817  

818 The new builders inherit work dependencies from the original builder. 

819  

820 Parameters 

821 ---------- 

822 condition : :class:`~graph.GraphCondition` 

823 The condition variable from :meth:`create_condition` selecting 

824 which case executes. 

825 count : int 

826 The number of cases to add to the switch conditional. 

827  

828 Returns 

829 ------- 

830 graph_builders : tuple[:obj:`~graph.GraphBuilder`, ...] 

831 A tuple of new graph builders, one for each branch. 

832  

833 """ 

834 GB_check_open(self) 1stuvw

835 if cy_driver_version() < (12, 8, 0): 1stuvw

836 raise RuntimeError(f"Driver version {'.'.join(map(str, cy_driver_version()))} does not support conditional switch") 

837 if not isinstance(condition, GraphCondition): 1stuvw

838 raise TypeError( 

839 f"condition must be a GraphCondition object (from " 

840 f"GraphBuilder.create_condition()), got {type(condition).__name__}") 

841 node_params = driver.CUgraphNodeParams() 1stuvw

842 node_params.type = driver.CUgraphNodeType.CU_GRAPH_NODE_TYPE_CONDITIONAL 1stuvw

843 node_params.conditional.handle = condition.handle 1stuvw

844 node_params.conditional.type = driver.CUgraphConditionalNodeType.CU_GRAPH_COND_TYPE_SWITCH 1stuvw

845 node_params.conditional.size = count 1stuvw

846 node_params.conditional.ctx = self._get_conditional_context() 1stuvw

847 return GB_cond_with_params(self, node_params) 1stuvw

848  

849 def while_loop(self, GraphCondition condition not None: GraphCondition) -> GraphBuilder: 

850 """Adds a while loop and returns a new graph builder for it. 

851  

852 The resulting while loop graph will execute the branch repeatedly at runtime 

853 until the condition evaluates to false. 

854  

855 The new builder inherits work dependencies from the original builder. 

856  

857 Parameters 

858 ---------- 

859 condition : :class:`~graph.GraphCondition` 

860 The condition variable from :meth:`create_condition` controlling 

861 loop continuation. 

862  

863 Returns 

864 ------- 

865 graph_builder : :obj:`~graph.GraphBuilder` 

866 The newly created while loop graph builder. 

867  

868 """ 

869 GB_check_open(self) 1BCDE

870 if cy_driver_version() < (12, 3, 0): 1BCDE

871 raise RuntimeError(f"Driver version {'.'.join(map(str, cy_driver_version()))} does not support conditional while loop") 

872 if not isinstance(condition, GraphCondition): 1BCDE

873 raise TypeError( 

874 f"condition must be a GraphCondition object (from " 

875 f"GraphBuilder.create_condition()), got {type(condition).__name__}") 

876 node_params = driver.CUgraphNodeParams() 1BCDE

877 node_params.type = driver.CUgraphNodeType.CU_GRAPH_NODE_TYPE_CONDITIONAL 1BCDE

878 node_params.conditional.handle = condition.handle 1BCDE

879 node_params.conditional.type = driver.CUgraphConditionalNodeType.CU_GRAPH_COND_TYPE_WHILE 1BCDE

880 node_params.conditional.size = 1 1BCDE

881 node_params.conditional.ctx = self._get_conditional_context() 1BCDE

882 return GB_cond_with_params(self, node_params)[0] 1BCDE

883  

884 def embed(self, GraphBuilder child): 

885 """Embed a previously-built :obj:`~graph.GraphBuilder` as a child node. 

886  

887 Parameters 

888 ---------- 

889 child : :obj:`~graph.GraphBuilder` 

890 The child graph builder. Must have finished building. 

891 """ 

892 GB_check_open(self) 2obH J

893 GB_check_open(child) 2obH J

894 GB_check_has_graph(child) 2obH J

895 if child._state != CAPTURE_ENDED: 2obH J

896 raise ValueError("Child graph has not finished building.") 2ob

897  

898 if not self.is_building: 2obH J

899 raise ValueError("Parent graph is not being built.") 2ob

900  

901 stream_handle = self._stream.handle 1HJ

902 _, _, graph_out, *deps_info_out, num_dependencies_out = handle_return( 1HJ

903 driver.cuStreamGetCaptureInfo(stream_handle) 1HJ

904 ) 

905  

906 # See https://github.com/NVIDIA/cuda-python/pull/879#issuecomment-3211054159 

907 # for rationale 

908 dependencies_out = deps_info_out[0] 1HJ

909 new_node = handle_return( 1HJ

910 driver.cuGraphAddChildGraphNode( 1HJ

911 graph_out, dependencies_out, 

912 num_dependencies_out, as_py(child._h_graph) 1HJ

913 ) 

914 ) 

915 cdef cydriver.CUgraphNode c_new_node = ( 

916 <cydriver.CUgraphNode><intptr_t>int(new_node) 1HJ

917 ) 

918 cdef cydriver.CUgraph embedded_graph = NULL 1HJ

919 cdef cydriver.CUresult rollback_status 

920 cdef GraphHandle h_embedded 

921 try: 1HJ

922 with nogil: 1HJ

923 HANDLE_RETURN(cydriver.cuGraphChildGraphNodeGetGraph( 1HJ

924 c_new_node, &embedded_graph)) 

925 h_embedded = create_child_graph_handle( 1HJ

926 embedded_graph, self._h_graph, c_new_node) 

927 HANDLE_RETURN(graph_clone_attachments( 1HJ

928 h_embedded, child._h_graph)) 

929 except: 

930 with nogil: 

931 rollback_status = cydriver.cuGraphDestroyNode(c_new_node) 

932 if rollback_status == cydriver.CUDA_SUCCESS: 

933 invalidate_child_graph_state( 

934 self._h_graph, c_new_node) 

935 else: 

936 # The original exception propagates with the failed rollback 

937 # attached as a note (error handling policy). 

938 attach_rollback_failure( 

939 b"cuGraphDestroyNode", rollback_status, 

940 b"failed while rolling back a child graph node; the node remains in the graph") 

941 raise 

942  

943 deps_info_update = [[new_node]] + [None] * (len(deps_info_out) - 1) 1HJ

944 handle_return( 1HJ

945 driver.cuStreamUpdateCaptureDependencies( 1HJ

946 stream_handle, 1HJ

947 *deps_info_update, # dependencies, edgeData 

948 1, 

949 driver.CUstreamUpdateCaptureDependencies_flags.CU_STREAM_SET_CAPTURE_DEPENDENCIES, 1HJ

950 ) 

951 ) 

952  

953 def callback(self, fn: Callable[..., object], *, user_data: int | BufferProtocol | None = None) -> None: 

954 """Add a host callback to the graph during stream capture. 

955  

956 The callback runs on the host CPU when the graph reaches this point 

957 in execution. Two modes are supported: 

958  

959 - **Python callable**: Pass any callable. The GIL is acquired 

960 automatically. The callable must take no arguments; use closures 

961 or ``functools.partial`` to bind state. 

962 - **ctypes function pointer**: The function receives a single 

963 ``void*`` argument (the ``user_data``), and the caller must keep 

964 the ctypes wrapper alive for the lifetime of the graph. Its 

965 declared prototype must match the driver's ``CUhostFn`` 

966 (``void (*)(void*)``): ``ctypes.CFUNCTYPE(None, ctypes.c_void_p)``, 

967 or ``ctypes.WINFUNCTYPE(None, ctypes.c_void_p)`` on Windows. 

968  

969 .. warning:: 

970  

971 Callbacks must not call CUDA API functions. Doing so may 

972 deadlock or corrupt driver state. 

973  

974 Use caution when a Python callback retains an object that owns a 

975 graph. Any reference cycle involving the callback and a graph that 

976 retains it cannot be broken by Python's cyclic garbage collector. 

977 Use a weak reference to break such cycles. 

978  

979 Parameters 

980 ---------- 

981 fn : callable or ctypes function pointer 

982 The callback function. 

983 user_data : int or bytes-like, optional 

984 Only for ctypes function pointers. If ``int``, passed as a raw 

985 pointer (caller manages lifetime). If bytes-like, the data is 

986 copied and its lifetime is tied to the graph. 

987  

988 Raises 

989 ------ 

990 TypeError 

991 If ``fn`` is a ctypes function pointer whose declared prototype 

992 does not match ``CUhostFn``. 

993 ValueError 

994 If ``user_data`` is given for a Python callable, or if ``fn`` is 

995 :data:`HOST_COPY_FN` and ``user_data`` is not a packed record. 

996 """ 

997 GB_callback(self, fn, user_data, False) 2~czbL M N O J K I

998  

999  

1000cdef inline void GB_callback( 

1001 GraphBuilder gb, object fn, object user_data, 

1002 bint fail_tail_discovery_for_testing) except *: 

1003 GB_check_open(gb) 2~cP zbL M N O J K I

1004 cdef Stream stream = gb._stream 2~cP zbL M N O J K I

1005 cdef cydriver.CUstream c_stream = as_cu(stream._h_stream) 2~cP zbL M N O J K I

1006 cdef cydriver.CUstreamCaptureStatus capture_status 

1007  

1008 with nogil: 2~cP zbL M N O J K I

1009 _get_capture_info(c_stream, &capture_status, NULL) 2~cP zbL M N O J K I

1010  

1011 if capture_status != cydriver.CU_STREAM_CAPTURE_STATUS_ACTIVE: 2~cP zbL M N O J K I

1012 raise RuntimeError("Cannot add callback when graph is not being built") 2~c

1013  

1014 cdef cydriver.CUhostFn c_fn 

1015 cdef void* c_user_data = NULL 2P zbL M N O J K I

1016 cdef OpaqueHandle fn_owner, data_owner 

1017 cdef PreparedAttachment prepared 

1018 _resolve_host_callback( 2P zbL M N O J K I

1019 fn, user_data, &c_fn, &c_user_data, &fn_owner, &data_owner) 

1020 HANDLE_RETURN(graph_prepare_attachment( 1PLMNOJKI

1021 gb._h_graph, fn_owner, data_owner, &prepared)) 

1022  

1023 with nogil: 1PLMNOJKI

1024 HANDLE_RETURN(cydriver.cuLaunchHostFunc(c_stream, c_fn, c_user_data)) 1PLMNOJKI

1025  

1026 # Capturing the host function added a node to the graph; it is now the 

1027 # stream's sole capture dependency. Attach the callback's owners to it. 

1028 cdef cydriver.CUgraphNode host_node 

1029 cdef cydriver.CUresult commit_status 

1030 try: 1PLMNOJKI

1031 if fail_tail_discovery_for_testing: 1PLMNOJKI

1032 raise RuntimeError("forced capture tail discovery failure") 1P

1033 host_node = _capture_tail_node(c_stream) 1LMNOJKI

1034 except BaseException as orig_exc: 1P

1035 # CUDA added the callback, but its node cannot be identified. 

1036 # Retain its owners anonymously to prevent dangling pointers. 

1037 commit_status = graph_commit_attachment(prepared, NULL) 1P

1038 try: 1P

1039 HANDLE_RETURN(commit_status) 1P

1040 except Exception as commit_exc: 

1041 raise commit_exc from orig_exc 

1042 raise 1P

1043 HANDLE_RETURN(graph_commit_attachment(prepared, host_node)) 1LMNOJKI

1044  

1045  

1046def _capture_callback_with_tail_failure_for_testing( 

1047 GraphBuilder gb, fn, *, user_data=None): 

1048 """Exercise anonymous attachment retention after node discovery fails.""" 

1049 GB_callback(gb, fn, user_data, True) 1P

1050  

1051  

1052cdef inline int GB_check_open(GraphBuilder gb) except -1: 

1053 """Reject operations on a builder that has been closed. 

1054  

1055 A CLOSED builder has reset its stream and graph handles, so any method 

1056 that dereferences them would read a null handle (or, for the cached 

1057 Stream, a None typed as cdef Stream). Guarding here yields a clear error 

1058 instead. 

1059 """ 

1060 if gb._state == CLOSED: 2`c~cP Cbnb9bidpbobF lbibjbnd1bqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

1061 raise RuntimeError("GraphBuilder has been closed") 2`cnbqb# rb6 }c

1062 return 0 2`c~cP Cb9bidpbobF lbibjbnd1bqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

1063  

1064  

1065cdef inline int GB_check_has_graph(GraphBuilder gb) except -1: 

1066 """Reject graph access on a builder whose capture ended invalidated. 

1067  

1068 The driver discards the capture graph when it ends an invalidated 

1069 capture, so such a builder has nothing to complete, print, embed, or 

1070 update from. 

1071 """ 

1072 if gb._state == CAPTURE_INVALIDATED: 2P pbobF lbibjbL M N O cbH : x z adsb3 mby G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] fb* a @ K I ~ [

1073 raise RuntimeError( 2lbibjb

1074 "The capture was invalidated and the driver discarded its graph; " 

1075 "this graph builder has no graph.") 

1076 return 0 2P pbobF L M N O cbH : x z adsb3 mby G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] fb* a @ K I ~ [

1077  

1078  

1079cdef inline cydriver.CUresult GB_end_capture(GraphBuilder gb) noexcept: 

1080 """End the capture if this builder owns a live one, and settle ownership 

1081 of the graph. Returns the driver status; the caller raises or reports it. 

1082  

1083 Only a CAPTURING PRIMARY or CONDITIONAL_BODY builder owns the live 

1084 capture. A FORKED builder must not call cuStreamEndCapture: the driver 

1085 requires forked streams to be joined first. 

1086  

1087 On success the driver hands back the graph this builder already holds. 

1088 When the capture was invalidated (or left unjoined), the driver destroys 

1089 the capture graph and returns NULL. The owning handle a PRIMARY builder 

1090 took in begin_building() must then forget that graph rather than destroy 

1091 it a second time, and the builder ends up with no graph at all. 

1092 """ 

1093 cdef cydriver.CUgraph c_graph = NULL 2`c~cP Cbnb9bidpbobF lbibjbnd1bqdqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

1094 cdef cydriver.CUresult err = cydriver.CUDA_SUCCESS 2`c~cP Cbnb9bidpbobF lbibjbnd1bqdqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

1095 cdef cydriver.CUstream c_stream 

1096 if not gb._h_stream or gb._state != CAPTURING or gb._kind == FORKED: 2`c~cP Cbnb9bidpbobF lbibjbnd1bqdqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by *bDbG T U ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

1097 return err 2`c~cP CbnbidpbobF lbibjbnd1bqdqbzbL M N O cbH : # x S z rbadQbZ sb3 mb4by DbG T U ; ld5 = 6 kbpd4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ {c|cK I ~ kdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c[

1098 c_stream = as_cu(gb._h_stream) 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

1099 with nogil: 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

1100 err = cydriver.cuStreamEndCapture(c_stream, &c_graph) 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

1101 if c_graph == NULL: 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

1102 # Only a PRIMARY builder owns a graph hierarchy to retire. A 

1103 # CONDITIONAL_BODY graph belongs to the parent's conditional node; the 

1104 # driver destroys it as well when the body capture ends invalidated and 

1105 # leaves the parent graph referring to it, which cuda.core cannot 

1106 # repair (see the end_building docstring). Only this builder's alias 

1107 # is dropped here. 

1108 if gb._kind == PRIMARY: 2Cb9blbibjbT U

1109 invalidate_root_graph_state(gb._h_graph) 2Cb9blbibjbT U

1110 gb._h_graph.reset() 2Cb9blbibjbT U

1111 gb._state = CAPTURE_INVALIDATED 2Cb9blbibjbT U

1112 else: 

1113 gb._state = CAPTURE_ENDED 2P pbobF 1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

1114 return err 2P Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

1115  

1116  

1117cdef inline cydriver.CUresult GB_close(GraphBuilder gb) noexcept: 

1118 """Close the builder and return the status of ending its capture. 

1119  

1120 The builder is closed whatever that status is. close() raises it; join() 

1121 attaches it to the error already propagating. 

1122 """ 

1123 cdef cydriver.CUresult err = GB_end_capture(gb) 2`cCbnbF lbibjbqb: # rbZ mby G T U = 6 b c d e f g h i j k l m n o p q r s t u v a tbAbubvb{c|ckdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c

1124 gb._h_graph.reset() 2`cCbnbF lbibjbqb: # rbZ mby G T U = 6 b c d e f g h i j k l m n o p q r s t u v a tbAbubvb{c|ckdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c

1125 gb._h_stream.reset() 2`cCbnbF lbibjbqb: # rbZ mby G T U = 6 b c d e f g h i j k l m n o p q r s t u v a tbAbubvb{c|ckdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c

1126 retry_deferred_cleanup() 2`cCbnbF lbibjbqb: # rbZ mby G T U = 6 b c d e f g h i j k l m n o p q r s t u v a tbAbubvb{c|ckdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c

1127 gb._state = CLOSED 2`cCbnbF lbibjbqb: # rbZ mby G T U = 6 b c d e f g h i j k l m n o p q r s t u v a tbAbubvb{c|ckdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c

1128 gb._stream = None 2`cCbnbF lbibjbqb: # rbZ mby G T U = 6 b c d e f g h i j k l m n o p q r s t u v a tbAbubvb{c|ckdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c

1129 return err 2`cCbnbF lbibjbqb: # rbZ mby G T U = 6 b c d e f g h i j k l m n o p q r s t u v a tbAbubvb{c|ckdIbJbEbKbLbFbMbNbGbObHbwbxbybBb}c

1130  

1131  

1132cdef inline GraphBuilder GB_init_forked(Stream stream, GraphHandle h_primary_graph): 

1133 cdef GraphBuilder gb = GraphBuilder.__new__(GraphBuilder) 1F#ZyGTUbcdefghijklmnopqrstuva

1134 # A FORKED builder captures into the primary's CUgraph. It holds the 

1135 # primary's GraphHandle so conditional bodies share its graph hierarchy. 

1136 gb._h_graph = h_primary_graph 1F#ZyGTUbcdefghijklmnopqrstuva

1137 gb._h_stream = stream._h_stream 1F#ZyGTUbcdefghijklmnopqrstuva

1138 gb._kind = FORKED 1F#ZyGTUbcdefghijklmnopqrstuva

1139 gb._state = CAPTURING 1F#ZyGTUbcdefghijklmnopqrstuva

1140 gb._stream = stream 1F#ZyGTUbcdefghijklmnopqrstuva

1141 return gb 1F#ZyGTUbcdefghijklmnopqrstuva

1142  

1143  

1144cdef inline GraphBuilder GB_init_conditional( 

1145 Stream stream, cydriver.CUgraph cond_graph, 

1146 GraphBuilder parent, cydriver.CUgraphNode owner_node): 

1147 cdef GraphBuilder gb = GraphBuilder.__new__(GraphBuilder) 1xSzbcdefghijklmnopqArstuvBCDEwa

1148 gb._h_graph = create_child_graph_handle( 1xSzbcdefghijklmnopqArstuvBCDEwa

1149 cond_graph, parent._h_graph, owner_node) 

1150 gb._h_stream = stream._h_stream 1xSzbcdefghijklmnopqArstuvBCDEwa

1151 gb._kind = CONDITIONAL_BODY 1xSzbcdefghijklmnopqArstuvBCDEwa

1152 gb._state = CAPTURE_NOT_STARTED 1xSzbcdefghijklmnopqArstuvBCDEwa

1153 gb._stream = stream 1xSzbcdefghijklmnopqArstuvBCDEwa

1154 return gb 1xSzbcdefghijklmnopqArstuvBCDEwa

1155  

1156  

1157cdef inline int _get_capture_info( 

1158 cydriver.CUstream stream, 

1159 cydriver.CUstreamCaptureStatus* status, 

1160 cydriver.CUgraph* graph) except?-1 nogil: 

1161 """Thin wrapper around ``cuStreamGetCaptureInfo`` that papers over the 

1162 CUDA 12 vs 13 signature change. 

1163  

1164 ``status`` must be non-NULL: the driver rejects ``captureStatus_out=NULL`` 

1165 with ``CUDA_ERROR_INVALID_VALUE``. ``graph`` may be NULL when the caller 

1166 does not need the graph handle. 

1167 """ 

1168 IF CUDA_CORE_BUILD_MAJOR >= 13: 

1169 return HANDLE_RETURN(cydriver.cuStreamGetCaptureInfo( 2~cP Cb9bpbobF lbibjb1bqbzbL M N O cbH : # x S z rbQbZ sb3 mb4by *bDbG T U ; 5 = 6 kb4 b c d e f g h i j k l m n o p q A r s t u v B C D E J | ^ ` gbabdb!b8b} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( 2 R Q X Y / w 1 ) ? ] Pbfb* a tbAbubvb@ K I ~ IbJbEbKbLbFbMbNbGbObHbwbxbybBb[

1170 stream, status, NULL, graph, NULL, NULL, NULL)) 

1171 ELSE: 

1172 return HANDLE_RETURN(cydriver.cuStreamGetCaptureInfo( 

1173 stream, status, NULL, graph, NULL, NULL)) 

1174  

1175  

1176cdef inline cydriver.CUgraphNode _capture_tail_node(cydriver.CUstream stream) except *: 

1177 """Return the node a freshly-captured single-node operation left as the 

1178 stream's sole capture dependency (e.g. the host node added by 

1179 ``cuLaunchHostFunc``). The driver advances the stream's dependency set to 

1180 the new node, so the next captured op would depend on it. 

1181 """ 

1182 cdef cydriver.CUstreamCaptureStatus status 

1183 cdef const cydriver.CUgraphNode* deps = NULL 1LMNOJKI

1184 cdef size_t num_deps = 0 1LMNOJKI

1185 with nogil: 1LMNOJKI

1186 IF CUDA_CORE_BUILD_MAJOR >= 13: 

1187 HANDLE_RETURN(cydriver.cuStreamGetCaptureInfo( 1LMNOJKI

1188 stream, &status, NULL, NULL, &deps, NULL, &num_deps)) 

1189 ELSE: 

1190 HANDLE_RETURN(cydriver.cuStreamGetCaptureInfo( 

1191 stream, &status, NULL, NULL, &deps, &num_deps)) 

1192 if num_deps != 1: 1LMNOJKI

1193 raise RuntimeError( 

1194 f"expected exactly one capture dependency after a host callback, got {num_deps}") 

1195 return <cydriver.CUgraphNode>deps[0] 1LMNOJKI

1196  

1197  

1198cdef inline tuple GB_cond_with_params(GraphBuilder gb, node_params): 

1199 status, _, graph, *deps_info, num_dependencies = handle_return( 2x S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

1200 driver.cuStreamGetCaptureInfo(gb._stream.handle) 2x S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

1201 ) 

1202 if status != driver.CUstreamCaptureStatus.CU_STREAM_CAPTURE_STATUS_ACTIVE: 2x S z kbb c d e f g h i j k l m n o p q A r s t u v B C D E w a

1203 raise RuntimeError("Cannot add conditional node when not actively capturing") 2kb

1204  

1205 new_node = handle_return( 1xSzbcdefghijklmnopqArstuvBCDEwa

1206 driver.cuGraphAddNode(graph, *deps_info, num_dependencies, node_params)) 1xSzbcdefghijklmnopqArstuvBCDEwa

1207 deps_info_update = [[new_node]] + [None] * (len(deps_info) - 1) 1xSzbcdefghijklmnopqArstuvBCDEwa

1208  

1209 handle_return( 1xSzbcdefghijklmnopqArstuvBCDEwa

1210 driver.cuStreamUpdateCaptureDependencies( 1xSzbcdefghijklmnopqArstuvBCDEwa

1211 gb._stream.handle, 1xSzbcdefghijklmnopqArstuvBCDEwa

1212 *deps_info_update, # dependencies, edgeData 1xSzbcdefghijklmnopqArstuvBCDEwa

1213 1, # numDependencies 

1214 driver.CUstreamUpdateCaptureDependencies_flags.CU_STREAM_SET_CAPTURE_DEPENDENCIES, 1xSzbcdefghijklmnopqArstuvBCDEwa

1215 ) 

1216 ) 

1217  

1218 return tuple( 1xSzbcdefghijklmnopqArstuvBCDEwa

1219 GB_init_conditional( 1xSzbcdefghijklmnopqArstuvBCDEwa

1220 gb._stream.device.create_stream(), 1xSzbcdefghijklmnopqArstuvBCDEwa

1221 <cydriver.CUgraph><intptr_t>int(node_params.conditional.phGraph_out[i]), 1xSzbcdefghijklmnopqArstuvBCDEwa

1222 gb, 1xSzbcdefghijklmnopqArstuvBCDEwa

1223 <cydriver.CUgraphNode><intptr_t>int(new_node), 1xSzbcdefghijklmnopqArstuvBCDEwa

1224 ) 

1225 for i in range(node_params.conditional.size) 1xSzbcdefghijklmnopqArstuvBCDEwa

1226 ) 

1227  

1228  

1229cdef class Graph: 

1230 """An executable graph. 

1231  

1232 A graph groups a set of CUDA kernels and other CUDA operations together and executes 

1233 them with a specified dependency tree. It speeds up the workflow by combining the 

1234 driver activities associated with CUDA kernel launches and CUDA API calls. 

1235  

1236 Graphs must be built using a :obj:`~graph.GraphBuilder` object. 

1237  

1238 """ 

1239  

1240 def __init__(self): 

1241 raise RuntimeError("directly constructing a Graph instance is not supported") 2qd

1242  

1243 @staticmethod 

1244 cdef Graph _init(GraphExecHandle h_graph_exec): 

1245 cdef Graph self = Graph.__new__(Graph) 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcdded5bscgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b* @ K I ~ [

1246 self._h_graph_exec = h_graph_exec 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcdded5bscgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b* @ K I ~ [

1247 return self 2P nbF L M N O cbH : x z 3 y G ; 5 = 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'bwcbdcdxcdded5bscgdyczcAc_b`bhdBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc| ^ ` gbabdb} _ { hbbbeb+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b* @ K I ~ [

1248  

1249 def close(self) -> None: 

1250 """Destroy the graph.""" 

1251 self._h_graph_exec.reset() 2nb: = 5bsctcucvc|b* K I ~

1252 retry_deferred_cleanup() 2nb: = 5bsctcucvc|b* K I ~

1253  

1254 @property 

1255 def is_closed(self) -> bool: 

1256 """Whether this executable graph has been closed.""" 

1257 return self._h_graph_exec.get() == NULL 2nb

1258  

1259 @property 

1260 def handle(self) -> driver.CUgraphExec: 

1261 """Return the underlying ``CUgraphExec`` object. 

1262  

1263 .. caution:: 

1264  

1265 This handle is a Python object. To get the memory address of the underlying C 

1266 handle, call ``int()`` on the returned object. 

1267  

1268 """ 

1269 return as_py(self._h_graph_exec) 2: /c

1270  

1271 @overload 

1272 def __getitem__(self, node: KernelNode) -> ExecutableKernelNode: ... 

1273 @overload 

1274 def __getitem__(self, node: MemsetNode) -> ExecutableMemsetNode: ... 

1275 @overload 

1276 def __getitem__(self, node: MemcpyNode) -> ExecutableMemcpyNode: ... 

1277 @overload 

1278 def __getitem__(self, node: ChildGraphNode) -> ExecutableChildGraphNode: ... 

1279 @overload 

1280 def __getitem__(self, node: EventRecordNode) -> ExecutableEventRecordNode: ... 

1281 @overload 

1282 def __getitem__(self, node: EventWaitNode) -> ExecutableEventWaitNode: ... 

1283 @overload 

1284 def __getitem__(self, node: HostCallbackNode) -> ExecutableHostCallbackNode: ... 

1285  

1286 def __getitem__(self, GraphNode node not None: GraphNode) -> ExecutableGraphNode: 

1287 """Return a view for updating *node* in this executable graph. 

1288  

1289 *node* is a definition node from the graph used to instantiate this 

1290 executable. Call ``update()`` on the returned view to replace that 

1291 node's parameters for future launches. Kernel, memcpy, and memset 

1292 views also support enabling and disabling the node. 

1293 """ 

1294 Graph_check_open(self) 2nbac|bbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpcRb2bR Q qcrc3b

1295 GN_check_valid(node) 2ac|bbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpcRb2bR Q qcrc3b

1296 return create_executable_node_view( 2ac|bbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpcRb2bR Q qcrc3b

1297 self._h_graph_exec, node) 2ac|bbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpcRb2bR Q qcrc3b

1298  

1299 def update(self, source: "GraphBuilder | GraphDefinition") -> None: 

1300 """Update the graph using a new graph definition. 

1301  

1302 The topology of the provided source must be identical to this graph. 

1303  

1304 Parameters 

1305 ---------- 

1306 source : :obj:`~graph.GraphBuilder` or :obj:`~graph.GraphDefinition` 

1307 The graph definition to update from. A GraphBuilder must have 

1308 finished building. 

1309  

1310 """ 

1311 Graph_check_open(self) 2nb6 Rb2bR Q X Y 3b6b7bw 1 (b)b) ? ]

1312 cdef GraphHandle h_source 

1313  

1314 if isinstance(source, GraphBuilder): 26 Rb2bR Q X Y 3b6b7bw 1 (b)b) ? ]

1315 GB_check_open(<GraphBuilder>source) 16w1)?

1316 GB_check_has_graph(<GraphBuilder>source) 1w1)?

1317 if (<GraphBuilder>source)._state != CAPTURE_ENDED: 1w1)?

1318 raise ValueError("Graph has not finished building.") 1?

1319 h_source = (<GraphBuilder>source)._h_graph 1w1)

1320 elif isinstance(source, GraphDefinition): 2Rb2bR Q X Y 3b6b7b(b)b]

1321 GD_check_valid(<GraphDefinition>source) 2Rb2bR Q X Y 3b6b7b(b)b

1322 h_source = (<GraphDefinition>source)._h_graph 2Rb2bR Q X Y 3b6b7b(b)b

1323 else: 

1324 raise TypeError( 1]

1325 f"expected GraphBuilder or GraphDefinition, got {type(source).__name__}") 1]

1326  

1327 cdef cydriver.CUgraphExecUpdateResultInfo result_info 

1328 cdef cydriver.CUresult err = graph_exec_update( 2Rb2bR Q X Y 3b6b7bw 1 (b)b)

1329 self._h_graph_exec, h_source, &result_info) 

1330 if err == cydriver.CUresult.CUDA_ERROR_GRAPH_EXEC_UPDATE_FAILURE: 2Rb2bR Q X Y 3b6b7bw 1 (b)b)

1331 reason = driver.CUgraphExecUpdateResult(result_info.result) 2RbQ 6b7b)

1332 msg = f"Graph update failed: {reason.__doc__.strip()} ({reason.name})" 2RbQ 6b7b)

1333 raise CUDAError(msg) 2RbQ 6b7b)

1334 HANDLE_RETURN(err) 22bR X Y 3bw 1 (b)b

1335  

1336 def upload(self, Stream stream not None: Stream) -> None: 

1337 """Uploads the graph in a stream. 

1338  

1339 Parameters 

1340 ---------- 

1341 stream : :obj:`~_stream.Stream` 

1342 The stream in which to upload the graph 

1343  

1344 """ 

1345 Graph_check_open(self) 2nby 5 +b,b-b.b/bSb:bTb;b=b?b@bUb[bVbWbXb]bYbZb^b0b_b`b{b+ 7 $ , 8 % 0 V W - 9 ' . ! ( }b~bI

1346 cdef Stream s = Stream_accept(stream) 2y 5 +b,b-b.b/bSb:bTb;b=b?b@bUb[bVbWbXb]bYbZb^b0b_b`b{b+ 7 $ , 8 % 0 V W - 9 ' . ! ( }b~bI

1347 cdef cydriver.CUgraphExec c_exec = as_cu(self._h_graph_exec) 2y 5 +b,b-b.b/bSb:bTb;b=b?b@bUb[bVbWbXb]bYbZb^b0b_b`b{b+ 7 $ , 8 % 0 V W - 9 ' . ! ( }b~bI

1348 cdef cydriver.CUstream c_stream = as_cu(s._h_stream) 2y 5 +b,b-b.b/bSb:bTb;b=b?b@bUb[bVbWbXb]bYbZb^b0b_b`b{b+ 7 $ , 8 % 0 V W - 9 ' . ! ( }b~bI

1349 with nogil: 2y 5 +b,b-b.b/bSb:bTb;b=b?b@bUb[bVbWbXb]bYbZb^b0b_b`b{b+ 7 $ , 8 % 0 V W - 9 ' . ! ( }b~bI

1350 HANDLE_RETURN(cydriver.cuGraphUpload(c_exec, c_stream)) 2y 5 +b,b-b.b/bSb:bTb;b=b?b@bUb[bVbWbXb]bYbZb^b0b_b`b{b+ 7 $ , 8 % 0 V W - 9 ' . ! ( }b~bI

1351  

1352 def launch(self, Stream stream not None: Stream) -> None: 

1353 """Launches the graph in a stream. 

1354  

1355 Parameters 

1356 ---------- 

1357 stream : :obj:`~_stream.Stream` 

1358 The stream in which to launch the graph. 

1359  

1360 """ 

1361 Graph_check_open(self) 2P nbL M N O H x z 3 y ; 5 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'b5bscyczcAc_b`bBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc2 ccdcecfcgchcicjckclcmcncocpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b}b~b@ K I [

1362 cdef Stream s = Stream_accept(stream) 2P L M N O H x z 3 y ; 5 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'b5bscyczcAc_b`bBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc2 ccdcecfcgchcicjckclcmcncocpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b}b~b@ K I [

1363 cdef cydriver.CUgraphExec c_exec = as_cu(self._h_graph_exec) 2P L M N O H x z 3 y ; 5 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'b5bscyczcAc_b`bBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc2 ccdcecfcgchcicjckclcmcncocpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b}b~b@ K I [

1364 cdef cydriver.CUstream c_stream = as_cu(s._h_stream) 2P L M N O H x z 3 y ; 5 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'b5bscyczcAc_b`bBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc2 ccdcecfcgchcicjckclcmcncocpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b}b~b@ K I [

1365 with nogil: 2P L M N O H x z 3 y ; 5 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'b5bscyczcAc_b`bBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc2 ccdcecfcgchcicjckclcmcncocpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b}b~b@ K I [

1366 HANDLE_RETURN(cydriver.cuGraphLaunch(c_exec, c_stream)) 2P L M N O H x z 3 y ; 5 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'b5bscyczcAc_b`bBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc2 ccdcecfcgchcicjckclcmcncocpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b}b~b@ K I [

1367  

1368  

1369cdef inline int Graph_check_open(Graph self) except -1: 

1370 if not self._h_graph_exec: 2P nbL M N O H x z 3 y ; 5 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'b5bscyczcAc_b`bBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b@ K I [

1371 raise RuntimeError("Graph has been closed") 2nb

1372 return 0 2P L M N O H x z 3 y ; 5 6 4 b c d e f g h i j k l m n o p q A r s t u v B C D E +b,b-b.b/bSb:bTb#b;b=b?b@bUb[bVb$bWbXb]bYb%bZb^b0b'b5bscyczcAc_b`bBctcucCcDcEcFcGcHcvcIcJcKcLcMc{bNcOcPcQcRcScTc+ 7 $ , 8 % 0 V W - 9 ' . ! ( ac|bUcVcWcXcYcZc0c1c2c3c4c5c6cbc:c;c=c?c@c2 [c]c^c/cccdcecfcgchcicjckclcmcncoc_cpc7c8c9c!c#c$c%c'c(c)c*c+c,cRb2b-c.cR Q X Y / qcrc3b6b7bw 1 (b)b) ? ] }b~b@ K I [