Skip to content

cuda.core: add atomic update methods for executable graph nodes #2354

Description

@Andy-Jost

Background

Part of #1330. Depends on #2350, #2352, and #2353.

CUDA supports individual executable-node updates but provides no parameter getters for CUgraphExec. A source CUgraph may also be modified independently after instantiation, so it cannot reliably represent the executable graph's current parameters.

Add exec-bound node update views that require complete replacement parameters and retain new owners through the append-only accumulator from #2353.

This feature requires CUDA 12.2+ and uses the generic cuGraphExecNodeSetParams API. Supporting CUDA 12.0/12.1 through the older typed setters is intentionally out of scope.

Proposed API

Index an executable graph with a node from the graph definition most recently used to instantiate or successfully update it:

graph[kernel_node].update(
    config=new_config,
    kernel=new_kernel,
    args=new_args,
)

graph[memcpy_node].update(
    dst=new_dst,
    src=new_src,
    size=new_size,
)

graph[memset_node].update(
    dst=new_dst,
    value=new_value,
    width=new_width,
    height=new_height,
    pitch=new_pitch,
)

graph[host_node].update(new_callback, user_data=new_user_data)
graph[child_node].update(new_child_graph)
graph[event_node].update(new_event)

exec_kernel = graph[kernel_node]
exec_kernel.disable()
assert not exec_kernel.is_enabled
exec_kernel.enable()

Unlike definition-level updates, executable-node updates require a complete parameter set. cuda.core does not cache or infer omitted values because it cannot query current executable-node state reliably.

The returned exec-bound view does not expose parameter properties as current executable state. Its purpose is to validate node identity and perform updates.

Source-node identity

GraphExecBox retains the graph definition hierarchy most recently used to instantiate or successfully update the exec.

  • graph[node] requires node to belong to that current source hierarchy, including a live descendant graph.
  • A successful Graph.update(source) changes the current source to source.
  • Views created from the previous source become stale and raise on further use.
  • A failed whole update leaves the current source and existing views unchanged.
  • Removing the source node makes subsequent individual updates unavailable, matching CUDA's requirement that the identifying node remain valid.
  • Modifying source-node parameters does not affect the exec and is not used to infer executable state.

Track a source generation solely to detect stale views; do not maintain an executable parameter cache.

Update transaction

Each update() call constructs one fully initialized, zero-padded CUgraphNodeParams from its complete arguments and invokes cuGraphExecNodeSetParams exactly once.

For owner-changing updates:

  1. Resolve all owners and construct the complete parameters.
  2. Record the current exec accumulator size.
  3. Append every required owner before calling CUDA.
  4. Call cuGraphExecNodeSetParams.
  5. On success, keep the appended owners.
  6. On failure, restore the accumulator to its previous size.

Successful updates never remove prior owners individually. Superseded owners remain until a successful Graph.update() replaces the accumulator or the executable graph is destroyed.

Raw addresses remain caller-owned and do not add accumulator entries.

Supported nodes

Implement exec-bound update() for:

  • KernelNode
  • MemcpyNode
  • MemsetNode
  • HostCallbackNode
  • ChildGraphNode
  • EventRecordNode
  • EventWaitNode

Empty nodes have no mutable parameters. CUDA does not support executable parameter updates for allocation, free, or conditional nodes.

Enable and disable

Exec-bound views for KernelNode, MemcpyNode, and MemsetNode additionally expose:

view.is_enabled
view.enable()
view.disable()

is_enabled queries cuGraphNodeGetEnabled and is not cached. enable() and disable() call cuGraphNodeSetEnabled and propagate driver failures through the normal CUDAError path. Both methods are idempotent. Parameter updates and whole-graph updates do not alter the executable node enable state.

Driver APIs

Use cuGraphExecNodeSetParams for every supported parameter update. Use cuGraphNodeGetEnabled and cuGraphNodeSetEnabled only for executable enable-state operations. Do not add version-based fallback to the older node-specific parameter setters.

Propagate driver failures through the normal CUDAError handling path and roll back newly appended owners when the driver rejects an update.

Whole-update integration

After successful Graph.update(source):

Whole-update failure changes none of this state.

Acceptance criteria

  • Every supported node type accepts a complete update and launches successfully on CUDA 12.2+.
  • Each public update results in one cuGraphExecNodeSetParams call.
  • No eager parameter snapshot or executable parameter cache is created.
  • Source-definition parameter changes are never mistaken for executable state.
  • Invalid updates leave executable parameters and accumulated ownership unchanged.
  • Required owners survive every launch that may use them.
  • Raw addresses remain caller-owned.
  • Successful whole updates invalidate old views and accept nodes from the new source.
  • Failed whole updates preserve existing views.
  • Superseded owners are reclaimed after a successful whole update or final exec destruction once CUDA releases in-flight references.
  • Multiple executable graphs maintain independent accumulators and source generations.
  • Documentation explains the complete-parameter requirement, lack of executable parameter getters, and CUDA 12.2+ requirement.
  • Kernel, memcpy, and memset views report and change their executable enable state without a cache.

Non-goals

  • CUDA 12.0/12.1 fallback through typed node setters.
  • Partial executable-node updates.
  • Reading current executable-node parameter values.
  • Property setters as mutation syntax.
  • Explicit removal of accumulated owners.
  • Coherent state after mutation through raw CUDA handles.

Metadata

Metadata

Assignees

Labels

P0High priority - Must do!cuda.coreEverything related to the cuda.core modulefeatureNew feature or request

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions