21#include "absl/memory/memory.h"
22#include "absl/random/distributions.h"
23#include "benchmark/benchmark.h"
24#include "gtest/gtest.h"
25#include "isp/fiber/auto_design/utils/parallelizer.h"
27#include "ortools/base/threadlocal.h"
30#include "ortools/graph/test_util.h"
35using Graph = StaticGraph<>;
42template <Implementation implementation>
43std::vector<std::vector<uint32_t>> ManyToManyShortestPaths(
44 const Graph&
graph,
const std::vector<uint32_t>& arc_costs,
45 const std::vector<int>& srcs,
const std::vector<int>& dsts,
47 LOG(FATAL) <<
"Default implementation of ManyToManyShortestPaths(); use a "
48 "specialization [Implementation="
49 << implementation <<
"].";
52template <Implementation implementation>
53std::vector<std::vector<uint32_t>> AllPairsShortestPaths(
54 const Graph&
graph,
const std::vector<uint32_t>& arc_costs,
56 std::vector<int> all_nodes(
graph.num_nodes(), -1);
57 std::iota(all_nodes.begin(), all_nodes.end(), 0);
58 return ManyToManyShortestPaths<implementation>(
graph, arc_costs, all_nodes,
59 all_nodes, num_threads);
63std::vector<std::vector<uint32_t>> ManyToManyShortestPaths<BOUNDED_DIJKSTRA>(
64 const Graph&
graph,
const std::vector<uint32_t>& arc_costs,
65 const std::vector<int>& srcs,
const std::vector<int>& dsts,
67 using Dijkstra = BoundedDijkstraWrapper<Graph, uint32_t>;
68 Dijkstra base_dijkstra(&
graph, &arc_costs);
69 std::vector<std::pair<int, uint32_t>> dsts_with_offsets;
70 for (
const int dst : dsts) {
71 dsts_with_offsets.push_back({dst, 0});
73 ThreadLocal<Dijkstra> thread_local_dijkstra(base_dijkstra);
74 std::vector<std::vector<uint32_t>> distances(
75 srcs.size(), std::vector<uint32_t>(dsts.size(), INT_MAX));
76 std::vector<int> src_to_src_index(
graph.num_nodes(), -1);
77 for (
int i = 0;
i < srcs.size(); ++
i) {
78 src_to_src_index[srcs[
i]] =
i;
80 std::vector<int> dst_to_dst_index(
graph.num_nodes(), -1);
81 for (
int i = 0;
i < dsts.size(); ++
i) {
82 dst_to_dst_index[dsts[
i]] =
i;
85 fiber_auto_design::Parallelizer(num_threads).Apply(
86 [&thread_local_dijkstra, &dsts_with_offsets, &src_to_src_index,
87 &dst_to_dst_index, &distances](
const int* src_ptr) {
88 const int src = *src_ptr;
89 Dijkstra*
const dij = thread_local_dijkstra.pointer();
90 for (
const int destination :
91 dij->RunBoundedDijkstraFromMultipleSourcesToMultipleDestinations(
92 {{src, 0}}, dsts_with_offsets,
93 dsts_with_offsets.size(),
95 distances[src_to_src_index[src]][dst_to_dst_index[destination]] =
96 dij->distances()[destination];
105std::vector<std::vector<uint32_t>> ManyToManyShortestPaths<SHORTEST_PATHS>(
106 const Graph&
graph,
const std::vector<uint32_t>& arc_costs,
107 const std::vector<int>& srcs,
const std::vector<int>& dsts,
109 PathContainer path_container;
112 graph, arc_costs, srcs, dsts, num_threads, &path_container);
113 std::vector<std::vector<uint32_t>> distances(
114 srcs.size(), std::vector<uint32_t>(dsts.size(), INT_MAX));
115 std::vector<int> src_to_src_index(
graph.num_nodes(), -1);
116 for (
int i = 0;
i < srcs.size(); ++
i) {
117 src_to_src_index[srcs[
i]] =
i;
119 std::vector<int> dst_to_dst_index(
graph.num_nodes(), -1);
120 for (
int i = 0;
i < dsts.size(); ++
i) {
121 dst_to_dst_index[dsts[
i]] =
i;
123 for (
const int src : srcs) {
124 for (
const int dst : dsts) {
125 distances[src_to_src_index[src]][dst_to_dst_index[dst]] =
126 path_container.GetDistance(src, dst);
132template <Implementation implementation>
133static void BM_MultiThreadAllPairsOn2DGrid(benchmark::State& state) {
135 const int grid_size = state.range(0);
136 const int num_threads = state.range(1);
138 std::unique_ptr<Graph>
graph =
139 util::Create2DGridGraph<Graph>(grid_size, grid_size);
140 std::vector<uint32_t> arc_costs(
graph->num_arcs(), 0);
141 std::mt19937 random(12345);
142 for (uint32_t& cost : arc_costs) {
143 cost = absl::Uniform(random, 0, 100000);
145 for (
auto _ : state) {
146 ::benchmark::DoNotOptimize(
147 AllPairsShortestPaths<implementation>(*
graph, arc_costs, num_threads));
150 state.SetBytesProcessed(state.iterations() *
graph->num_nodes() *
156BENCHMARK(BM_MultiThreadAllPairsOn2DGrid<BOUNDED_DIJKSTRA>)
168BENCHMARK(BM_MultiThreadAllPairsOn2DGrid<SHORTEST_PATHS>)
180template <Implementation implementation,
int num_threads>
181static void BM_WindowedAllPairsOn2DGrid(benchmark::State& state) {
185 const int grid_size = state.range(0);
186 const int window_size = state.range(1);
188 std::unique_ptr<Graph>
graph =
189 util::Create2DGridGraph<Graph>(grid_size, grid_size);
190 std::vector<uint32_t> arc_costs(
graph->num_arcs(), 0);
191 std::mt19937 random(12345);
192 for (uint32_t& cost : arc_costs) {
193 cost = absl::Uniform(random, 0, 100000);
195 std::vector<int> window_nodes;
196 const int window_start = (grid_size - window_size) / 2;
197 const int window_end = window_start + window_size;
198 for (
int i = window_start;
i < window_end; ++
i) {
199 for (
int j = window_start; j < window_end; ++j) {
200 window_nodes.push_back(i * grid_size + j);
203 for (
auto _ : state) {
204 ::benchmark::DoNotOptimize(ManyToManyShortestPaths<implementation>(
205 *
graph, arc_costs, window_nodes, window_nodes, num_threads));
208 state.SetBytesProcessed(state.iterations() * window_size * window_size);
211BENCHMARK(BM_WindowedAllPairsOn2DGrid<BOUNDED_DIJKSTRA, 1>)
215BENCHMARK(BM_WindowedAllPairsOn2DGrid<SHORTEST_PATHS, 1>)
219BENCHMARK(BM_WindowedAllPairsOn2DGrid<BOUNDED_DIJKSTRA, 8>)
223BENCHMARK(BM_WindowedAllPairsOn2DGrid<SHORTEST_PATHS, 8>)
227BENCHMARK(BM_WindowedAllPairsOn2DGrid<BOUNDED_DIJKSTRA, 16>)
231BENCHMARK(BM_WindowedAllPairsOn2DGrid<SHORTEST_PATHS, 16>)
static void BuildPathDistanceContainer(PathContainer *path_container)
Builds a path container which only stores distances between path nodes.
In SWIG mode, we don't want anything besides these top-level includes.
util::ReverseArcStaticGraph Graph
Type of graph to use.
void ComputeManyToManyShortestPathsWithMultipleThreads(const ListGraph<> &graph, const std::vector< PathDistance > &arc_lengths, const std::vector< ListGraph<>::NodeIndex > &sources, const std::vector< ListGraph<>::NodeIndex > &destinations, int num_threads, PathContainer *const path_container)