Skip to content

Commit

Permalink
Merge branch 'networkx:main' into wf_tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Schefflera-Arboricola authored Jan 6, 2024
2 parents 752fdce + aeb4eb2 commit 7089e8f
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 11 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,7 @@ dmypy.json

# Pyre type checker
.pyre/

# asv
results/
html/
18 changes: 8 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
## nx-parallel

nx-parallel is a NetworkX backend plugin that uses joblib and multiprocessing for parallelization. This project aims to provide parallelized implementations of various NetworkX functions to improve performance.
nx-parallel is a NetworkX backend that uses joblib for parallelization. This project aims to provide parallelized implementations of various NetworkX functions to improve performance.

## Features

nx-parallel provides parallelized implementations for the following NetworkX functions:

```
├── centrality
│ ├── betweenness_centrality
│ ├── closeness_vitality
├── tournament
│ ├── is_reachable
├── efficiency_measures
│ ├── local_efficiency
```
- [betweeness_centrality](https://github.com/networkx/nx-parallel/blob/main/nx_parallel/algorithms/centrality/betweenness.py#L17)
- [local_efficiency](https://github.com/networkx/nx-parallel/blob/main/nx_parallel/algorithms/efficiency_measures.py#L12)
- [number_of_isolates](https://github.com/networkx/nx-parallel/blob/main/nx_parallel/algorithms/isolate.py#L9)
- [all_pairs_bellman_ford_path](https://github.com/networkx/nx-parallel/blob/main/nx_parallel/algorithms/shortest_paths/weighted.py#L9)
- [is_reachable](https://github.com/networkx/nx-parallel/blob/main/nx_parallel/algorithms/tournament.py#L11)
- [tournament_is_strongly_connected](https://github.com/networkx/nx-parallel/blob/main/nx_parallel/algorithms/tournament.py#L103)
- [closeness_vitality](https://github.com/networkx/nx-parallel/blob/main/nx_parallel/algorithms/vitality.py#L9)

![alt text](timing/heatmap_all_functions.png)

Expand Down
22 changes: 22 additions & 0 deletions benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Preview benchmarks locally

1. clone this repo
2. `cd benchmarks`
3. If you are working on a different branch then update the `branches` in the `asv.conf.json` file.
4. `asv run` will run the benchmarks on the last commit
- or use `asv continuous base_commit_hash test_commit_hash` to run the benchmark to compare two commits
- or `asv run -b <benchmark_file_name> -k <benchmark_name>` to run a particular benchmark.
- if you are running benchmarks for the first time, you will be asked to enter your machine information after this command.
5. `asv publish` will create a `html` folder with the results
6. `asv preview` will host the results locally at http://127.0.0.1:8080/

<hr>

## Structure of benchmarks

* Each `bench_` file corresponds to a folder/file in the [networkx/algorithms](https://github.com/networkx/networkx/tree/main/networkx/algorithms) directory in NetworkX
* Each class inside a `bench_` file corresponds to every file in a folder(one class if it’s a file) in networkx/algorithms
* The class name corresponds to the file name and the `x` in `bench_x` corresponds to the folder name(class name and `x` are the same if it’s a file in networkx/algorithms)
* Each `time_` function corresponds to each function in the file.
* For other folders in [networkx/networkx](https://github.com/networkx/networkx/tree/main/networkx) like `generators`, `classes`, `linalg`, `utils` etc. we can have different `bench_` files for each of them having different classes corresponding to different files in each of these folders.
* For example: `bench_centrality.py` corresponds to `networkx/algorithms/centrality` folder in NetworkX and the `Betweenness` class inside it corresponds to the `betweenness.py` file in `networkx/algorithms/centrality` folder in NetworkX. And the `time_betweenness_centrality` function corresponds to the `betweenness_centrality` function.
20 changes: 20 additions & 0 deletions benchmarks/asv.conf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": 1,
"project": "nx-parallel",
"project_url": "https://github.com/networkx/nx-parallel",
"repo": "..",
"branches": ["main"],
"build_command": [
"python -m pip install build",
"python -m build --wheel -o {build_cache_dir} {build_dir}"
],
"dvcs": "git",
"environment_type": "virtualenv",
"show_commit_url": "https://github.com/networkx/nx-parallel/commit/",
"matrix": {"networkx": ["3.2"], "nx-parallel": []},
"benchmark_dir": "benchmarks",
"env_dir": "env",
"results_dir": "results",
"html_dir": "html",
"build_cache_size": 8
}
1 change: 1 addition & 0 deletions benchmarks/benchmarks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

11 changes: 11 additions & 0 deletions benchmarks/benchmarks/bench_centrality.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from .common import *
import networkx as nx


class Betweenness(Benchmark):
params = [(backends), (num_nodes), (edge_prob)]
param_names = ["backend", "num_nodes", "edge_prob"]

def time_betweenness_centrality(self, backend, num_nodes, edge_prob):
G = get_cached_gnp_random_graph(num_nodes, edge_prob)
_ = nx.betweenness_centrality(G, backend=backend)
11 changes: 11 additions & 0 deletions benchmarks/benchmarks/bench_efficiency_measures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from .common import *
import networkx as nx


class EfficiencyMeasures(Benchmark):
params = [(backends), (num_nodes), (edge_prob)]
param_names = ["backend", "num_nodes", "edge_prob"]

def time_local_efficiency(self, backend, num_nodes, edge_prob):
G = get_cached_gnp_random_graph(num_nodes, edge_prob)
_ = nx.local_efficiency(G, backend=backend)
11 changes: 11 additions & 0 deletions benchmarks/benchmarks/bench_isolate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from .common import *
import networkx as nx


class Isolate(Benchmark):
params = [(backends), (num_nodes), (edge_prob)]
param_names = ["backend", "num_nodes", "edge_prob"]

def time_number_of_isolates(self, backend, num_nodes, edge_prob):
G = get_cached_gnp_random_graph(num_nodes, edge_prob)
_ = nx.number_of_isolates(G, backend=backend)
11 changes: 11 additions & 0 deletions benchmarks/benchmarks/bench_shortest_paths.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from .common import *
import networkx as nx


class Weighted(Benchmark):
params = [(backends), (num_nodes), (edge_prob)]
param_names = ["backend", "num_nodes", "edge_prob"]

def time_all_pairs_bellman_ford_path(self, backend, num_nodes, edge_prob):
G = get_cached_gnp_random_graph(num_nodes, edge_prob, is_weighted=True)
_ = dict(nx.all_pairs_bellman_ford_path(G, backend=backend))
11 changes: 11 additions & 0 deletions benchmarks/benchmarks/bench_tournament.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from .common import *
import networkx as nx


class Tournament(Benchmark):
params = [(backends), (num_nodes)]
param_names = ["backend", "num_nodes"]

def time_is_reachable(self, backend, num_nodes):
G = nx.tournament.random_tournament(num_nodes, seed=42)
_ = nx.tournament.is_reachable(G, 1, num_nodes, backend=backend)
11 changes: 11 additions & 0 deletions benchmarks/benchmarks/bench_vitality.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from .common import *
import networkx as nx


class Vitality(Benchmark):
params = [(backends), (num_nodes), (edge_prob)]
param_names = ["backend", "num_nodes", "edge_prob"]

def time_closeness_vitality(self, backend, num_nodes, edge_prob):
G = get_cached_gnp_random_graph(num_nodes, edge_prob)
_ = nx.closeness_vitality(G, backend=backend)
33 changes: 33 additions & 0 deletions benchmarks/benchmarks/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from functools import lru_cache
from pathlib import Path
import random

import networkx as nx

__all__ = [
"backends",
"num_nodes",
"edge_prob",
"get_cached_gnp_random_graph",
"Benchmark",
]

CACHE_ROOT = Path(__file__).resolve().parent.parent / "env" / "nxp_benchdata"

backends = ["parallel", None]
num_nodes = [50, 100, 200, 400, 800]
edge_prob = [0.8, 0.6, 0.4, 0.2]


@lru_cache(typed=True)
def get_cached_gnp_random_graph(num_nodes, edge_prob, is_weighted=False):
G = nx.fast_gnp_random_graph(num_nodes, edge_prob, seed=42, directed=False)
if is_weighted:
random.seed(42)
for (u, v) in G.edges():
G.edges[u, v]["weight"] = random.random()
return G


class Benchmark:
pass
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ developer = [
'pytest',
]

[project.entry-points."networkx.plugins"]
[project.entry-points."networkx.backends"]
parallel = "nx_parallel.interface:Dispatcher"

[tool.setuptools]
Expand Down

0 comments on commit 7089e8f

Please sign in to comment.