cuGraph Reference
cuGraph is NVIDIA's GPU-accelerated graph analytics library within the RAPIDS ecosystem. It provides NetworkX-compatible APIs for graph algorithms, delivering 10-500x+ speedup over CPU-based NetworkX on medium to large graphs. It supports both a direct Python API and a **zero-code-change NetworkX backend** (nx-cugraph) that accelerates existing NetworkX code with no modifications.
Overview
cuGraph Reference
cuGraph is NVIDIA's GPU-accelerated graph analytics library within the RAPIDS ecosystem. It provides NetworkX-compatible APIs for graph algorithms, delivering 10-500x+ speedup over CPU-based NetworkX on medium to large graphs. It supports both a direct Python API and a zero-code-change NetworkX backend (nx-cugraph) that accelerates existing NetworkX code with no modifications.
Full documentation: https://docs.rapids.ai/api/cugraph/stable/ Version (stable): 26.02.00 Repository: https://github.com/rapidsai/cugraph
Table of Contents
- Installation and Setup
- Two Usage Modes
- nx-cugraph: Zero-Code-Change NetworkX Backend
- Direct cuGraph API
- Graph Creation and Data Loading
- Supported Graph Types
- Algorithm Catalog
- Multi-GPU Support with Dask
- GNN Support (cugraph-pyg and WholeGraph)
- Performance Characteristics and Benchmarks
- Memory Management
- Interoperability
- Known Limitations vs NetworkX
- Common Migration Patterns
Installation and Setup
Always use uv add (never pip install or conda install) in all install instructions, docstrings, comments, and error messages.
uv add --extra-index-url=https://pypi.nvidia.com cugraph-cu12 # Core cuGraph for CUDA 12.x
uv add --extra-index-url=https://pypi.nvidia.com nx-cugraph-cu12 # NetworkX backend
Platform: Linux and WSL2 only (no native macOS or Windows). Requires: NVIDIA GPU with CUDA 12.x support, NetworkX >= 3.2 (>= 3.4 recommended for optimal nx-cugraph).
Verify:
print(cugraph.__version__)
# Quick test with built-in dataset
from cugraph.datasets import karate
G = karate.get_graph()
result = cugraph.degree_centrality(G)
print(result.head())
Two Usage Modes
Mode 1: nx-cugraph Backend (Zero Code Change)
Accelerate existing NetworkX code by setting one environment variable. No code changes required.
NX_CUGRAPH_AUTOCONFIG=True python my_networkx_script.py
Mode 2: Direct cuGraph API
Use cuGraph's native API for maximum control, working directly with cuDF DataFrames and cuGraph graph objects.
edges = cudf.DataFrame({
"src": [0, 1, 2, 0],
"dst": [1, 2, 3, 3],
"weight": [1.0, 2.0, 1.5, 3.0]
})
G = cugraph.Graph()
G.from_cudf_edgelist(edges, source="src", destination="dst", edge_attr="weight")
result = cugraph.pagerank(G)
When to use which:
- nx-cugraph: Existing NetworkX codebases, rapid prototyping, when you want zero migration effort
- Direct API: Maximum performance, multi-GPU workflows, integration with cuDF/cuML pipelines, GNN training
nx-cugraph: Zero-Code-Change NetworkX Backend
nx-cugraph is a NetworkX backend that transparently redirects supported algorithm calls to GPU-accelerated cuGraph implementations.
How It Works
NetworkX >= 3.2 has a backend dispatch system. When nx-cugraph is installed and enabled, NetworkX automatically redirects supported function calls to GPU implementations. Unsupported calls fall back to default NetworkX.
Three Ways to Enable
1. Environment Variable (recommended for zero code change):
python my_script.py
# OR inline:
NX_CUGRAPH_AUTOCONFIG=True python my_script.py
2. Keyword Argument (explicit per-call):
result = nx.betweenness_centrality(G, k=10, backend="cugraph")
3. Type-Based Dispatch (explicit graph conversion):
G_nx = nx.karate_club_graph()
G_gpu = nxcg.from_networkx(G_nx) # Convert once, reuse for multiple algorithms
result = nx.pagerank(G_gpu) # Automatically dispatched to GPU
Supported Algorithms in nx-cugraph
Centrality:
betweenness_centrality,edge_betweenness_centralitydegree_centrality,in_degree_centrality,out_degree_centralityeigenvector_centrality,katz_centrality
Community:
louvain_communities,leiden_communities
Components:
connected_components,is_connected,number_connected_componentsnode_connected_componentweakly_connected_components,is_weakly_connected,number_weakly_connected_components
Clustering:
average_clustering,clustering,transitivity,triangles
Core:
core_number,k_truss
Link Analysis:
pagerank,hits
Link Prediction:
jaccard_coefficient
Shortest Paths (23+ functions):
shortest_path,shortest_path_lengthhas_path,all_pairs_shortest_path,all_pairs_shortest_path_lengthdijkstra_path,dijkstra_path_length,all_pairs_dijkstra,all_pairs_dijkstra_path_lengthbellman_ford_path,bellman_ford_path_length,all_pairs_bellman_ford_path_lengthsingle_source_shortest_path,single_source_shortest_path_lengthsingle_source_dijkstra,single_source_dijkstra_path,single_source_dijkstra_path_lengthsingle_source_bellman_ford,single_source_bellman_ford_path,single_source_bellman_ford_path_lengthsingle_target_shortest_path_length
Traversal:
bfs_edges,bfs_layers,bfs_predecessors,bfs_successors,bfs_treegeneric_bfs_edges,descendants_at_distance
DAG:
ancestors,descendants
Bipartite:
betweenness_centrality(bipartite),biadjacency_matrixcomplete_bipartite_graph,from_biadjacency_matrix
Tree:
is_arborescence,is_branching,is_forest,is_tree
Operators:
complement,reverse
Reciprocity:
overall_reciprocity,reciprocity
Isolate:
is_isolate,isolates,number_of_isolates
Lowest Common Ancestors:
lowest_common_ancestor
Layout:
forceatlas2_layout
Graph Generators: Various generators are also supported for creating graphs directly on GPU.
Direct cuGraph API
Quick Example
# Load edges from cuDF DataFrame
edges = cudf.DataFrame({
"source": [0, 1, 2, 3, 0, 2],
"destination": [1, 2, 3, 4, 4, 1],
"weight": [1.0, 2.0, 1.0, 3.0, 0.5, 1.5]
})
G = cugraph.Graph(directed=True)
G.from_cudf_edgelist(edges, source="source", destination="destination", edge_attr="weight")
# Run algorithms
pr = cugraph.pagerank(G)
bc = cugraph.betweenness_centrality(G)
components = cugraph.weakly_connected_components(G)
Graph Creation and Data Loading
From cuDF DataFrame (Primary Method)
df = cudf.DataFrame({"src": [0, 1, 2], "dst": [1, 2, 3], "wt": [1.0, 2.0, 3.0]})
# Unweighted
G = cugraph.Graph()
G.from_cudf_edgelist(df, source="src", destination="dst")
# Weighted
G = cugraph.Graph()
G.from_cudf_edgelist(df, source="src", destination="dst", edge_attr="wt")
# Directed
G = cugraph.Graph(directed=True)
G.from_cudf_edgelist(df, source="src", destination="dst")
From Pandas DataFrame
df = pd.DataFrame({"src": [0, 1, 2], "dst": [1, 2, 3]})
G = cugraph.Graph()
G.from_pandas_edgelist(df, source="src", destination="dst")
From cuDF Adjacency List
G = cugraph.Graph()
G.from_cudf_adjlist(offsets, indices, values) # CSR format
From NumPy Array
adj_matrix = np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]])
G = cugraph.Graph()
G.from_numpy_array(adj_matrix)
From Pandas Adjacency Matrix
G = cugraph.Graph()
G.from_pandas_adjacency(adj_df)
From Dask-cuDF (Multi-GPU)
G = cugraph.Graph()
G.from_dask_cudf_edgelist(dask_cudf_df, source="src", destination="dst")
From Built-in Datasets
from cugraph.datasets import karate, dolphins, polbooks, netscience
G = karate.get_graph()
Symmetrization (Undirected Graphs)
# Ensure all edges are bidirectional
sym_df = cugraph.symmetrize_df(df, "src", "dst")
# Or symmetrize a graph directly
sym_df = cugraph.symmetrize(source_col, dest_col, weight_col)
Vertex Renumbering
cuGraph internally renumbers vertices to contiguous integers starting from 0. Use unrenumber() to map back to original IDs:
result = cugraph.pagerank(G)
result = G.unrenumber(result, "vertex") # Map internal IDs back to original
Supported Graph Types
| Graph Type | cuGraph Class | Notes |
|---|---|---|
| Undirected | cugraph.Graph() | Default; edges are bidirectional |
| Directed | cugraph.Graph(directed=True) | Directed edges; some algorithms require directed/undirected |
| Weighted | Set edge_attr in from_cudf_edgelist | Edge weights used by SSSP, PageRank, Louvain, etc. |
| MultiGraph | cugraph.MultiGraph() | Multiple edges between same vertex pairs |
| Bipartite | Supported via standard Graph with bipartite structure | No dedicated class; algorithms in cugraph.bipartite |
Important: cuGraph uses a CSR (Compressed Sparse Row) internal representation. Graphs are immutable after creation -- you cannot dynamically add/remove individual edges after calling from_cudf_edgelist(). To modify a graph, reconstruct it from a new DataFrame.
Algorithm Catalog
Centrality
| Algorithm | Single-GPU | Multi-GPU | NetworkX Equivalent |
|---|---|---|---|
| Betweenness Centrality | cugraph.betweenness_centrality(G) | cugraph.dask.centrality.betweenness_centrality() | nx.betweenness_centrality() |
| Edge Betweenness | cugraph.edge_betweenness_centrality(G) | cugraph.dask.centrality.edge_betweenness_centrality() | nx.edge_betweenness_centrality() |
| Degree Centrality | cugraph.degree_centrality(G) | -- | nx.degree_centrality() |
| Eigenvector Centrality | cugraph.eigenvector_centrality(G) | cugraph.dask.centrality.eigenvector_centrality() | nx.eigenvector_centrality() |
| Katz Centrality | cugraph.katz_centrality(G) | cugraph.dask.centrality.katz_centrality() | nx.katz_centrality() |
Community Detection
| Algorithm | Single-GPU | Multi-GPU | NetworkX Equivalent |
|---|---|---|---|
| Louvain | cugraph.louvain(G, max_level=, max_iter=, resolution=) | cugraph.dask.community.louvain.louvain() | nx.community.louvain_communities() |
| Leiden | cugraph.leiden(G, max_iter=, resolution=) | cugraph.dask.community.leiden.leiden() | nx.community.leiden_communities() |
| ECG | cugraph.ecg(G, min_weight=) | cugraph.dask.community.ecg.ecg() | -- |
| Spectral Balanced Cut | cugraph.spectralBalancedCutClustering(G, num_clusters) | -- | -- |
| Spectral Modularity | cugraph.spectralModularityMaximizationClustering(G, num_clusters) | -- | -- |
| Triangle Counting | cugraph.triangle_count(G) | cugraph.dask.community.triangle_count() | nx.triangles() |
| K-Truss | cugraph.k_truss(G, k) or cugraph.ktruss_subgraph(G, k) | cugraph.dask.community.ktruss_subgraph() | nx.k_truss() |
| EgoNet | cugraph.ego_graph(G, n, radius=) | cugraph.dask.community.egonet() | nx.ego_graph() |
| Induced Subgraph | cugraph.induced_subgraph(G, vertices) | cugraph.dask.community.induced_subgraph() | G.subgraph(vertices) |
Clustering Analysis:
cugraph.analyzeClustering_edge_cut(G, n_clusters, clustering)cugraph.analyzeClustering_modularity(G, n_clusters, clustering)cugraph.analyzeClustering_ratio_cut(G, n_clusters, clustering)
Traversal
| Algorithm | Single-GPU | Multi-GPU | NetworkX Equivalent |
|---|---|---|---|
| BFS | cugraph.bfs(G, start=, depth_limit=) | cugraph.dask.traversal.bfs.bfs() | nx.bfs_edges() |
| BFS Edges | cugraph.bfs_edges(G, source) | -- | nx.bfs_edges() |
| SSSP | cugraph.sssp(G, source=) | cugraph.dask.traversal.sssp.sssp() | nx.single_source_dijkstra() |
| Shortest Path | cugraph.shortest_path(G, source=) | -- | nx.shortest_path() |
| Shortest Path Length | cugraph.shortest_path_length(G, source, target=) | -- | nx.shortest_path_length() |
| Filter Unreachable | cugraph.filter_unreachable(df) | -- | -- |
Link Analysis
| Algorithm | Single-GPU | Multi-GPU | NetworkX Equivalent |
|---|---|---|---|
| PageRank | cugraph.pagerank(G, alpha=) | cugraph.dask.link_analysis.pagerank() | nx.pagerank() |
| HITS | cugraph.hits(G, max_iter=, tol=) | cugraph.dask.link_analysis.hits() | nx.hits() |
Link Prediction / Similarity
| Algorithm | Single-GPU | Multi-GPU | NetworkX Equivalent |
|---|---|---|---|
| Jaccard | cugraph.jaccard(G, vertex_pair=) | -- | nx.jaccard_coefficient() |
| Cosine Similarity | cugraph.cosine(G, vertex_pair=) | -- | -- |
| Overlap | cugraph.overlap(G, vertex_pair=) | cugraph.dask.link_prediction.overlap() | -- |
| Sorensen | cugraph.sorensen(G, vertex_pair=) | cugraph.dask.link_prediction.sorensen() | -- |
NetworkX-compatible wrappers: cugraph.jaccard_coefficient(G, ebunch), cugraph.overlap_coefficient(G, ebunch), cugraph.sorensen_coefficient(G, ebunch)
Components
| Algorithm | Single-GPU | Multi-GPU | NetworkX Equivalent |
|---|---|---|---|
| Connected Components | cugraph.connected_components(G) | -- | nx.connected_components() |
| Weakly Connected | cugraph.weakly_connected_components(G) | cugraph.dask.components.weakly_connected_components() | nx.weakly_connected_components() |
| Strongly Connected | cugraph.strongly_connected_components(G) | -- | nx.strongly_connected_components() |
Cores
| Algorithm | Single-GPU | Multi-GPU | NetworkX Equivalent |
|---|---|---|---|
| Core Number | cugraph.core_number(G, degree_type=) | cugraph.dask.cores.core_number() | nx.core_number() |
| K-Core | cugraph.k_core(G, k=, core_number=) | cugraph.dask.cores.k_core() | nx.k_core() |
Sampling
| Algorithm | Single-GPU | Multi-GPU | Notes |
|---|---|---|---|
| Biased Random Walks | cugraph.biased_random_walks(G, start_vertices) | cugraph.dask.sampling.biased_random_walks() | Weighted/biased traversal |
| Uniform Random Walks | -- | cugraph.dask.sampling.uniform_random_walks() | Padded result with max path length |
| Random Walks | -- | cugraph.dask.sampling.random_walks() | General random walk |
| Node2Vec | -- | cugraph.dask.sampling.node2vec_random_walks() | Node2Vec sampling framework |
| Homogeneous Neighbor Sample | cugraph.homogeneous_neighbor_sample(G, start_vertices, fanout) | -- | Configurable fan-out per hop |
| Heterogeneous Neighbor Sample | cugraph.heterogeneous_neighbor_sample(G, ...) | -- | Multi-type node/edge graphs |
Layout
| Algorithm | Single-GPU | Multi-GPU | NetworkX Equivalent |
|---|---|---|---|
| Force Atlas 2 | cugraph.force_atlas2(G) | -- | `nx.forceatlas2_ |