101 lines
3.9 KiB
Python
101 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
|
|
"""Benchmark the neighbor search in graphs.
|
|
|
|
Initially written as part of
|
|
`Issue #90 <https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/pyrate/-/issues/90>`__ to determine
|
|
whether a faster implementation is needed.
|
|
That issue also contains a draft which *might* make it faster if that is required in the future.
|
|
|
|
Examples:
|
|
These are the benchmark results when run on a `Lenovo ThinkPad T560 laptop <https://thinkwiki.de/T560>`__
|
|
with an `Intel(R) Core(TM) i5-6300U CPU @ 2.40GHz
|
|
<https://ark.intel.com/content/www/de/de/ark/products/88190/intel-core-i5-6300u-processor-3m-cache-up-to-3-00-ghz.html>`__
|
|
and 16GB RAM (at commit ``9a8177326dc0d82d0aea4559e6c85071ceebf56f``):
|
|
|
|
.. code-block:: bash
|
|
|
|
./scripts/benchmark_graph_neighbor_search.py --iterations 100
|
|
frequency = 2 for distance 5000 km
|
|
generated graph in 0.018192768096923828 seconds
|
|
number of nodes = 42, number of edges = 120
|
|
non-empty entries in neighbor table = 240
|
|
computation time = 0.0003081770000221695 (avg. over 100 samples)
|
|
|
|
frequency = 8 for distance 1000 km
|
|
generated graph in 0.0327601432800293 seconds
|
|
number of nodes = 642, number of edges = 1920
|
|
non-empty entries in neighbor table = 3840
|
|
computation time = 0.0033796210000218707 (avg. over 100 samples)
|
|
|
|
frequency = 71 for distance 100 km
|
|
generated graph in 1.8711962699890137 seconds
|
|
number of nodes = 50412, number of edges = 151230
|
|
non-empty entries in neighbor table = 302460
|
|
computation time = 0.30925760600001695 (avg. over 100 samples)
|
|
|
|
frequency = 142 for distance 50 km
|
|
generated graph in 7.630561828613281 seconds
|
|
number of nodes = 201642, number of edges = 604920
|
|
non-empty entries in neighbor table = 1209840
|
|
computation time = 1.1302456550000102 (avg. over 100 samples)
|
|
|
|
frequency = 706 for distance 10 km
|
|
generated graph in 260.7689461708069 seconds
|
|
number of nodes = 4984362, number of edges = 14953080
|
|
non-empty entries in neighbor table = 29906160
|
|
computation time = 27.382845137000004 (avg. over 100 samples)
|
|
|
|
|
|
"""
|
|
|
|
# Standard library
|
|
from argparse import ArgumentDefaultsHelpFormatter
|
|
from argparse import ArgumentParser
|
|
from time import time
|
|
from timeit import timeit
|
|
|
|
# Scientific
|
|
import numpy
|
|
|
|
# Graph
|
|
from pyrate.plan.graph.generate import create_earth_graph
|
|
from pyrate.plan.graph.generate import min_required_frequency
|
|
from pyrate.plan.graph import NavigationGraph
|
|
|
|
|
|
def _main() -> None:
|
|
"""The main function."""
|
|
parser = ArgumentParser(
|
|
description="Benchmark the neighbor search in graphs.", formatter_class=ArgumentDefaultsHelpFormatter
|
|
)
|
|
parser.add_argument(
|
|
"--iterations", type=int, default=100, help="the number of timing samples to collect per graph size"
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
for distance_km in [5000, 1000, 100, 50, 10]:
|
|
frequency = min_required_frequency(distance_km * 1000, in_meters=True)
|
|
print(f"frequency = {frequency} for distance {distance_km} km")
|
|
|
|
time_before_generation = time()
|
|
graph = create_earth_graph(frequency, print_status=False)
|
|
print(f"generated graph in {time() - time_before_generation} seconds")
|
|
print(f"number of nodes = {len(graph)}, number of edges = {graph.num_edges}")
|
|
|
|
def setup(local_graph: NavigationGraph = graph) -> None:
|
|
local_graph._neighbors = None # pylint: disable=protected-access
|
|
|
|
def statement(local_graph: NavigationGraph = graph) -> None:
|
|
_ = local_graph.neighbors
|
|
|
|
avg_time = timeit(setup=setup, stmt=statement, number=args.iterations)
|
|
print(f"non-empty entries in neighbor table = {numpy.count_nonzero(graph.neighbors != -1)}")
|
|
print(f"computation time = {avg_time} (avg. over {args.iterations} samples)")
|
|
|
|
print() # empty line between distances
|
|
|
|
|
|
if __name__ == "__main__":
|
|
_main()
|