You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add GraphNode identity cache for stable object round-trips (#1853)
* Reorganize graph test files for clarity
Rename test files to reflect what they actually test:
- test_basic -> test_graph_builder (stream capture tests)
- test_conditional -> test_graph_builder_conditional
- test_advanced -> test_graph_update (moved child_graph and
stream_lifetime tests into test_graph_builder)
- test_capture_alloc -> test_graph_memory_resource
- test_explicit* -> test_graphdef*
Made-with: Cursor
* Enhance Graph.update() and add whole-graph update tests
- Extend Graph.update() to accept both GraphBuilder and GraphDef sources
- Surface CUgraphExecUpdateResultInfo details on update failure instead
of a generic CUDA_ERROR_GRAPH_EXEC_UPDATE_FAILURE message
- Release the GIL during cuGraphExecUpdate via nogil block
- Add parametrized happy-path test covering both GraphBuilder and GraphDef
- Add error-case tests: unfinished builder, topology mismatch, wrong type
Made-with: Cursor
* Add AdjacencySet proxy for pred/succ and GraphNode.remove()
Replace cached tuple-based pred/succ with mutable AdjacencySet backed
by direct CUDA driver calls. Add GraphNode.remove() wrapping
cuGraphDestroyNode.
Made-with: Cursor
* Add edge mutation support and MutableSet interface for GraphNode adjacencies
Enable adding/removing edges between graph nodes via AdjacencySet (a
MutableSet proxy on GraphNode.pred/succ), node removal via discard(),
and property setters for bulk edge replacement. Includes comprehensive
mutation and interface tests.
Closes part of #1330 (step 2: edge mutation on GraphDef).
Made-with: Cursor
* Use requires_module mark for numpy version checks in mutation tests
Replace inline skipif version check with requires_module(np, "2.1")
from the shared test helpers, consistent with other test files.
Made-with: Cursor
* Fix empty-graph return type: return set() instead of () for nodes/edges
Made-with: Cursor
* Rename AdjacencySet to AdjacencySetProxy, add bulk ops and safety guards
Rename class and file to AdjacencySetProxy to clarify write-through
semantics. Add bulk-efficient clear(), __isub__(), __ior__() overrides
and remove_edges() on the Cython core. Guard GraphNode.discard() against
double-destroy via membership check. Filter duplicates in update(). Add
error-path tests for wrong types, cross-graph edges, and self-edges.
Made-with: Cursor
* Add destroy() method with handle invalidation, remove GRAPH_NODE_SENTINEL
Replace discard() with destroy() which calls cuGraphDestroyNode and then
zeroes the CUgraphNode resource in the handle box via
invalidate_graph_node_handle. This prevents stale memory access on
destroyed nodes. Properties (type, pred, succ, handle) degrade gracefully
to None/empty for destroyed nodes.
Remove the GRAPH_NODE_SENTINEL (0x1) approach in favor of using NULL for
both sentinels and destroyed nodes, which is simpler and avoids the risk
of passing 0x1 to driver APIs that treat it as a valid pointer.
Made-with: Cursor
* Add GraphNode identity cache for stable Python object round-trips
Nodes retrieved via GraphDef.nodes(), edges(), or pred/succ traversal
now return the same Python object that was originally created, enabling
identity checks with `is`. A C++ HandleRegistry deduplicates
CUgraphNode handles, and a Cython WeakValueDictionary caches the
Python wrapper objects.
Made-with: Cursor
* Purge node cache on destroy to prevent stale identity lookups
Made-with: Cursor
* Skip NULL nodes in graph_node_registry to fix sentinel identity collision
Sentinel (entry) nodes use NULL as their CUgraphNode, so caching them
under a NULL key caused all sentinels across different graphs to share
the same handle. This made nodes built from the wrong graph's entry
point, causing CUDA_ERROR_INVALID_VALUE for conditional nodes and hash
collisions in equality tests.
Made-with: Cursor
* Unregister destroyed nodes from C++ graph_node_registry
When a node is destroyed, the driver may reuse its CUgraphNode pointer
for a new node. Without unregistering the old entry, the registry
returns a stale handle pointing to the wrong node type and graph.
Made-with: Cursor
* Add dedicated test for node identity preservation through round-trips
Made-with: Cursor
* Rename _node_cache/_cached to _node_registry/_registered
Aligns Python-side terminology with the C++ graph_node_registry.
Made-with: Cursor
* Fix unregister_handle and rename invalidate_graph_node_handle
unregister_handle: remove the expired() guard that prevented erasure
when the shared_ptr was still alive. This caused stale registry
entries after destroy(), leading to CUDA_ERROR_INVALID_VALUE when
the driver reused CUgraphNode pointer values.
Rename invalidate_graph_node_handle -> invalidate_graph_node for
consistency with the rest of the graph node API.
Made-with: Cursor
0 commit comments