Backends#
NetworkX can hand an algorithm to a backend, a separately installed package
such as nx-parallel (multicore
CPU) or nx-cugraph (NVIDIA GPU),
through its dispatch mechanism (nx._dispatchable). See NetworkX’s
backends guide
for how backends are installed and configured.
What is dispatchable#
Every function that takes a graph and returns a scored copy of it is dispatchable, as NetworkX’s own algorithms are:
statistical scorers (
disparity_filter,noise_corrected_filter,marginal_likelihood_filter,ecm_filter,lans_filter,multiple_linkage_analysis,polya_filter,gloss_filter);every structural method (
global_threshold_filter,metric_backbone,h_backbone,maximum_spanning_tree_backbone, …);proximity scores,
glab_filter, and the unweighted sparsifiers (sparsify,lspar,local_degree);multigraph_to_weighted,threshold_filter,fraction_filter,boolean_filter, andtransform_weights.
These functions accept the backend= keyword and follow
nx.config.backend_priority. They are registered under the dispatch name
"backbone_" + name (disparity_filter is "backbone_disparity_filter"),
because NetworkX keeps one registry of names for all packages:
adamic_adar_index and resource_allocation_index are already NetworkX
link-prediction functions, which nx-parallel implements.
The other functions are not dispatchable. The bipartite functions accept
incidence matrices as well as graphs, the hypergraph functions take lists of
hyperedges, the evaluation measures return numbers,
consensus_backbone takes any number of graphs, and the temporal functions
take snapshots (several graphs) or a multigraph of events or spans.
Using a backend#
No backend implements a backbone_* function yet, so
backend="parallel" raises NotImplementedError. backend="networkx"
(the default) always works:
import networkx as nx
import nx_backbone as nb
G = nx.les_miserables_graph()
H = nb.metric_backbone(G, backend="networkx")
A backend can still speed up the NetworkX algorithms that the backbone
methods call, such as all_pairs_dijkstra_path_length (metric backbone)
and edge_betweenness_centrality (edge_betweenness_filter,
h_backbone). List the backend in nx.config.backend_priority; the
backbone function runs its NetworkX code, and each NetworkX algorithm that
the backend implements runs on the backend:
# pip install nx-parallel
with nx.config.backend_priority(algos=["parallel"]):
H = nb.edge_betweenness_filter(G)
# or for the whole session
nx.config.backend_priority.algos = ["parallel"]
Setting the environment variable NETWORKX_BACKEND_PRIORITY=parallel
before importing NetworkX does the same. nx-parallel’s own settings, such as
the number of jobs, are under nx.config.backends.parallel.
NetworkX caches the converted graph on the input graph
(G.__networkx_cache__), so a second call on the same graph skips the
conversion and warns that the cache is being used. The cache is only correct
if the graph has not been modified in place since; see
nx.config.cache_converted_graphs and
nx.config.warnings_to_ignore.
Measured timings#
scripts/benchmark_backends.py times the shortest-path methods on a
Barabási-Albert graph with 1,000 nodes and 2,991 integer-weighted edges (the
seeded graph in benchmarks/benchmarks/_data.py), with and without
nx-parallel 0.4 in backend_priority. Best of 3 runs, Python 3.13, NetworkX
3.7, 4 CPUs, nx-parallel’s default n_jobs=-1:
Method |
NetworkX (s) |
parallel (s) |
Ratio |
Max diff |
|---|---|---|---|---|
|
2.23 |
2.13 |
1.05 |
0.0e+00 |
|
4.29 |
1.13 |
3.79 |
3.5e-18 |
|
1.82 |
0.54 |
3.38 |
1.4e-14 |
|
3.16 |
3.40 |
0.93 |
0.0e+00 |
|
3.50 |
3.84 |
0.91 |
0.0e+00 |
Ratio is the NetworkX time divided by the nx-parallel time. Max diff is
the largest difference between any score the two runs return. nx-parallel
adds up edge betweenness in a different order, so those scores can differ in
the last bits; on this graph every *_keep flag was the same. These
timings are from one machine. Measure on your own graphs and hardware before
relying on them.
high_salience_skeleton and glab_filter run one single-source search
per node (dijkstra_predecessor_and_distance), which nx-parallel 0.4 does
not implement, so they gain nothing. metric_backbone calls
all_pairs_dijkstra_path_length, which nx-parallel implements, but it was
not faster here.
Testing with a backend#
The test suite can run under NetworkX’s dispatch test harness, as NetworkX’s
own tests do. With nx_loopback, the test backend that ships with
NetworkX, every dispatchable call converts its input graphs, runs, and
checks that the result equals the plain NetworkX result:
NETWORKX_TEST_BACKEND=nx_loopback pytest --doctest-modules nx_backbone tests
Add NETWORKX_FALLBACK_TO_NX=1 to run with NetworkX the functions a
backend does not implement, instead of marking their tests as expected
failures.
The narrative guide Scaling up to large networks puts these timings next to run times measured at build time and the other ways to handle large networks.