Skip to content

Commit 73f77d5

Browse files
committed
Self review
1 parent e466bec commit 73f77d5

2 files changed

Lines changed: 37 additions & 25 deletions

File tree

cuda_core/cuda/core/experimental/_graph.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
1+
# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

@@ -84,7 +84,7 @@ class CompleteOptions:
8484
auto_free_on_launch : bool, optional
8585
Automatically free memory allocated in a graph before relaunching. (Default to False)
8686
upload_stream : Stream, optional
87-
Automatically upload the graph after instantiation. (Default to None)
87+
Stream to use to automatically upload the graph after completion. (Default to None)
8888
device_launch : bool, optional
8989
Configure the graph to be launchable from the device. This flag can only
9090
be used on platforms which support unified addressing. This flag cannot be
@@ -96,7 +96,7 @@ class CompleteOptions:
9696
"""
9797

9898
auto_free_on_launch: bool = False
99-
upload_stream: bool = None
99+
upload_stream: Optional[Stream] = None
100100
device_launch: bool = False
101101
use_node_priority: bool = False
102102

@@ -138,7 +138,7 @@ def close(self):
138138
def __init__(self):
139139
raise NotImplementedError(
140140
"directly creating a Graph object can be ambiguous. Please either "
141-
"call Device.create_graph() or stream.creating_graph()"
141+
"call Device.create_graph_builder() or stream.creating_graph_builder()"
142142
)
143143

144144
@classmethod
@@ -190,15 +190,15 @@ def is_building(self) -> bool:
190190
elif capture_status == driver.CUstreamCaptureStatus.CU_STREAM_CAPTURE_STATUS_INVALIDATED:
191191
self.end_building()
192192
raise RuntimeError(
193-
"Build process encountered an error and has been invalidated. Build process has now been ended."
193+
"Build process encountered an error and has been invalidated. Build process has been ended."
194194
)
195195
else:
196196
raise NotImplementedError(f"Unsupported capture status type received: {capture_status}")
197197

198198
def end_building(self) -> GraphBuilder:
199199
"""Ends the building process."""
200200
if not self.is_building:
201-
raise RuntimeError("Graph builder was not building.")
201+
raise RuntimeError("Graph builder is not building.")
202202
self._mnff.graph = handle_return(driver.cuStreamEndCapture(self.stream.handle))
203203

204204
# TODO: Resolving https://github.com/NVIDIA/cuda-python/issues/617 would allow us to
@@ -256,7 +256,7 @@ def complete(self, options: Optional[CompleteOptions] = None) -> Graph:
256256
elif params.result_out == driver.CUgraphInstantiateResult.CUDA_GRAPH_INSTANTIATE_CONDITIONAL_HANDLE_UNUSED:
257257
raise RuntimeError("One or more conditional handles are not associated with conditional builders.")
258258
elif params.result_out != driver.CUgraphInstantiateResult.CUDA_GRAPH_INSTANTIATE_SUCCESS:
259-
raise RuntimeError("Graph instantiation failed for an unexpected reason.")
259+
raise RuntimeError(f"Graph instantiation failed with unexpected error code: {params.result_out}")
260260
return graph
261261

262262
def debug_dot_print(self, path, options: Optional[DebugPrintOptions] = None):
@@ -265,7 +265,7 @@ def debug_dot_print(self, path, options: Optional[DebugPrintOptions] = None):
265265
Parameters
266266
----------
267267
path : str
268-
The path to the file to write the DOT debug output to.
268+
File path to use for writting debug DOT output
269269
options : :obj:`~_graph.DebugPrintOptions`, optional
270270
Customizable dataclass for the debug print options.
271271
@@ -313,7 +313,7 @@ def split(self, count) -> Tuple[GraphBuilder, ...]:
313313
"""Splits the original graph builder into multiple graph builders.
314314
315315
The new builders inherit work dependencies from the original builder.
316-
The original builder is reused for the split, returned first in the tuple.
316+
The original builder is reused for the split and is returned first in the tuple.
317317
318318
Parameters
319319
----------
@@ -407,7 +407,7 @@ def create_conditional_handle(self, default_value=None) -> int:
407407
The newly created conditional handle.
408408
409409
"""
410-
if default_value:
410+
if default_value != None:
411411
flags = driver.CU_GRAPH_COND_ASSIGN_DEFAULT
412412
else:
413413
default_value = 0
@@ -441,7 +441,7 @@ def _cond_with_params(self, node_params) -> GraphBuilder:
441441
)
442442
)
443443

444-
# Create new graph builders for each conditional
444+
# Create new graph builders for each condition
445445
return tuple(
446446
[
447447
GraphBuilder._init(

cuda_core/tests/test_graph.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,6 @@
1919
from cuda.core.experimental._memory import _DefaultPinnedMemorySource
2020

2121

22-
def test_graph_is_building(init_cuda):
23-
gb = Device().create_graph_builder()
24-
assert gb.is_building is False
25-
gb.begin_building()
26-
assert gb.is_building is True
27-
gb.end_building()
28-
assert gb.is_building is False
29-
30-
3122
def _common_kernels():
3223
code = """
3324
extern "C" __device__ __cudart_builtin__ void CUDARTAPI cudaGraphSetConditional(cudaGraphConditionalHandle handle,
@@ -48,6 +39,15 @@ def _common_kernels():
4839
return mod
4940

5041

42+
def test_graph_is_building(init_cuda):
43+
gb = Device().create_graph_builder()
44+
assert gb.is_building is False
45+
gb.begin_building()
46+
assert gb.is_building is True
47+
gb.end_building()
48+
assert gb.is_building is False
49+
50+
5151
def test_graph_straight(init_cuda):
5252
mod = _common_kernels()
5353
empty_kernel = mod.get_kernel("empty_kernel")
@@ -75,11 +75,18 @@ def test_graph_fork_join(init_cuda):
7575
gb = Device().create_graph_builder().begin_building()
7676
launch(gb, LaunchConfig(grid=1, block=1), empty_kernel)
7777

78+
with pytest.raises(ValueError, match="^Invalid split count: expecting >= 2, got 1"):
79+
gb.split(1)
80+
7881
left, right = gb.split(2)
7982
launch(left, LaunchConfig(grid=1, block=1), empty_kernel)
8083
launch(left, LaunchConfig(grid=1, block=1), empty_kernel)
8184
launch(right, LaunchConfig(grid=1, block=1), empty_kernel)
8285
launch(right, LaunchConfig(grid=1, block=1), empty_kernel)
86+
87+
with pytest.raises(ValueError, match="^Must join with at least two graph builders"):
88+
GraphBuilder.join(left)
89+
8390
gb = GraphBuilder.join(left, right)
8491

8592
launch(gb, LaunchConfig(grid=1, block=1), empty_kernel)
@@ -135,7 +142,7 @@ def test_graph_is_join_required(init_cuda):
135142

136143
# Create final node
137144
launch(gb, LaunchConfig(grid=1, block=1), empty_kernel)
138-
gb.end_building()
145+
gb.end_building().complete()
139146

140147

141148
@pytest.mark.skipif(tuple(int(i) for i in np.__version__.split(".")[:2]) < (2, 1), reason="need numpy 2.1.0+")
@@ -161,17 +168,17 @@ def test_graph_repeat_capture(init_cuda):
161168
assert arr[0] == 1
162169

163170
# Continue capturing to extend the graph
164-
with pytest.raises(RuntimeError):
171+
with pytest.raises(RuntimeError, match="^Cannot resume building after building has ended."):
165172
gb.begin_building()
166173

167174

168175
def test_graph_capture_errors(init_cuda):
169176
gb = Device().create_graph_builder()
170-
with pytest.raises(RuntimeError):
177+
with pytest.raises(RuntimeError, match="^Graph has not finished building."):
171178
gb.complete()
172179

173180
gb.begin_building()
174-
with pytest.raises(RuntimeError):
181+
with pytest.raises(RuntimeError, match="^Graph has not finished building."):
175182
gb.complete()
176183
gb.end_building().complete()
177184

@@ -286,7 +293,7 @@ def test_graph_conditional_if_else(init_cuda, condition_value):
286293
assert arr[1] == 3
287294

288295

289-
@pytest.mark.parametrize("condition_value", [0, 1, 2])
296+
@pytest.mark.parametrize("condition_value", [0, 1, 2, 3])
290297
def test_graph_conditional_switch(init_cuda, condition_value):
291298
mod = _common_kernels()
292299
add_one = mod.get_kernel("add_one")
@@ -358,6 +365,11 @@ def test_graph_conditional_switch(init_cuda, condition_value):
358365
assert arr[0] == 1
359366
assert arr[1] == 0
360367
assert arr[2] == 3
368+
elif condition_value == 3:
369+
# No branch is taken if case index is out of range
370+
assert arr[0] == 1
371+
assert arr[1] == 0
372+
assert arr[2] == 0
361373

362374

363375
@pytest.mark.parametrize("condition_value", [True, False])

0 commit comments

Comments
 (0)