From 26c909b64bbbb7994895eb57551db9c3f9021d04 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 18 Aug 2017 22:31:04 +0000 Subject: [PATCH] Refactor contractor to pass in graph directly --- include/contractor/graph_contractor.hpp | 43 +++--- .../contractor/graph_contractor_adaptors.hpp | 77 ++++++++++- include/util/dynamic_graph.hpp | 2 + src/contractor/contractor.cpp | 3 +- src/contractor/graph_contractor.cpp | 127 ++++-------------- 5 files changed, 123 insertions(+), 129 deletions(-) diff --git a/include/contractor/graph_contractor.hpp b/include/contractor/graph_contractor.hpp index 8e641b022..dfd43f364 100644 --- a/include/contractor/graph_contractor.hpp +++ b/include/contractor/graph_contractor.hpp @@ -95,10 +95,9 @@ class GraphContractor }; public: - GraphContractor(int nodes, std::vector input_edge_list); + GraphContractor(ContractorGraph graph); - GraphContractor(int nodes, - std::vector edges, + GraphContractor(ContractorGraph graph, std::vector node_levels_, std::vector node_weights_); @@ -119,18 +118,18 @@ class GraphContractor util::UnbufferedLog log; log << "Getting edges of minimized graph "; - util::Percent p(log, contractor_graph->GetNumberOfNodes()); - const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes(); - if (contractor_graph->GetNumberOfNodes()) + util::Percent p(log, graph.GetNumberOfNodes()); + const NodeID number_of_nodes = graph.GetNumberOfNodes(); + if (graph.GetNumberOfNodes()) { Edge new_edge; for (const auto node : util::irange(0u, number_of_nodes)) { p.PrintStatus(node); - for (auto edge : contractor_graph->GetAdjacentEdgeRange(node)) + for (auto edge : graph.GetAdjacentEdgeRange(node)) { - const NodeID target = contractor_graph->GetTarget(edge); - const ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(edge); + const NodeID target = graph.GetTarget(edge); + const ContractorGraph::EdgeData &data = graph.GetEdgeData(edge); if (!orig_node_id_from_new_node_id_map.empty()) { new_edge.source = orig_node_id_from_new_node_id_map[node]; @@ -163,7 +162,7 @@ class GraphContractor } } } - contractor_graph.reset(); + graph = ContractorGraph{}; orig_node_id_from_new_node_id_map.clear(); orig_node_id_from_new_node_id_map.shrink_to_fit(); @@ -198,10 +197,10 @@ class GraphContractor constexpr bool REVERSE_DIRECTION_ENABLED = true; constexpr bool REVERSE_DIRECTION_DISABLED = false; - for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node)) + for (auto in_edge : graph.GetAdjacentEdgeRange(node)) { - const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge); - const NodeID source = contractor_graph->GetTarget(in_edge); + const ContractorEdgeData &in_data = graph.GetEdgeData(in_edge); + const NodeID source = graph.GetTarget(in_edge); if (source == node) continue; @@ -221,14 +220,14 @@ class GraphContractor EdgeWeight max_weight = 0; unsigned number_of_targets = 0; - for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node)) + for (auto out_edge : graph.GetAdjacentEdgeRange(node)) { - const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge); + const ContractorEdgeData &out_data = graph.GetEdgeData(out_edge); if (!out_data.forward) { continue; } - const NodeID target = contractor_graph->GetTarget(out_edge); + const NodeID target = graph.GetTarget(out_edge); if (node == target) { continue; @@ -298,22 +297,22 @@ class GraphContractor SIMULATION_SEARCH_SPACE_SIZE, max_weight, node, - *contractor_graph); + graph); } else { const int constexpr FULL_SEARCH_SPACE_SIZE = 2000; dijkstra.Run( - number_of_targets, FULL_SEARCH_SPACE_SIZE, max_weight, node, *contractor_graph); + number_of_targets, FULL_SEARCH_SPACE_SIZE, max_weight, node, graph); } - for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node)) + for (auto out_edge : graph.GetAdjacentEdgeRange(node)) { - const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge); + const ContractorEdgeData &out_data = graph.GetEdgeData(out_edge); if (!out_data.forward) { continue; } - const NodeID target = contractor_graph->GetTarget(out_edge); + const NodeID target = graph.GetTarget(out_edge); if (target == node) continue; @@ -408,7 +407,7 @@ class GraphContractor // This bias function takes up 22 assembly instructions in total on X86 bool Bias(const NodeID a, const NodeID b) const; - std::shared_ptr contractor_graph; + ContractorGraph graph; ExternalVector external_edge_list; std::vector orig_node_id_from_new_node_id_map; std::vector node_levels; diff --git a/include/contractor/graph_contractor_adaptors.hpp b/include/contractor/graph_contractor_adaptors.hpp index 2bb123e2a..ced445b8f 100644 --- a/include/contractor/graph_contractor_adaptors.hpp +++ b/include/contractor/graph_contractor_adaptors.hpp @@ -4,6 +4,8 @@ #include "contractor/contractor_graph.hpp" #include "util/log.hpp" +#include + #include namespace osrm @@ -13,15 +15,14 @@ namespace contractor // Make sure to move in the input edge list! template -std::vector adaptToContractorInput(InputEdgeContainer input_edge_list) +ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer input_edge_list) { std::vector edges; edges.reserve(input_edge_list.size() * 2); for (const auto &input_edge : input_edge_list) { - if (input_edge.data.weight == INVALID_EDGE_WEIGHT) - continue; + BOOST_ASSERT(input_edge.data.weight < INVALID_EDGE_WEIGHT); #ifndef NDEBUG const unsigned int constexpr DAY_IN_DECI_SECONDS = 24 * 60 * 60 * 10; @@ -52,10 +53,74 @@ std::vector adaptToContractorInput(InputEdgeContainer input_edge false, input_edge.data.backward ? true : false, input_edge.data.forward ? true : false); + }; + tbb::parallel_sort(edges.begin(), edges.end()); + + NodeID edge = 0; + for (NodeID i = 0; i < edges.size();) + { + const NodeID source = edges[i].source; + const NodeID target = edges[i].target; + const NodeID id = edges[i].data.id; + // remove eigenloops + if (source == target) + { + ++i; + continue; + } + ContractorEdge forward_edge; + ContractorEdge reverse_edge; + forward_edge.source = reverse_edge.source = source; + forward_edge.target = reverse_edge.target = target; + forward_edge.data.forward = reverse_edge.data.backward = true; + forward_edge.data.backward = reverse_edge.data.forward = false; + forward_edge.data.shortcut = reverse_edge.data.shortcut = false; + forward_edge.data.id = reverse_edge.data.id = id; + forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1; + forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT; + forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION; + // remove parallel edges + while (i < edges.size() && edges[i].source == source && edges[i].target == target) + { + if (edges[i].data.forward) + { + forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight); + forward_edge.data.duration = + std::min(edges[i].data.duration, forward_edge.data.duration); + } + if (edges[i].data.backward) + { + reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight); + reverse_edge.data.duration = + std::min(edges[i].data.duration, reverse_edge.data.duration); + } + ++i; + } + // merge edges (s,t) and (t,s) into bidirectional edge + if (forward_edge.data.weight == reverse_edge.data.weight) + { + if ((int)forward_edge.data.weight != INVALID_EDGE_WEIGHT) + { + forward_edge.data.backward = true; + edges[edge++] = forward_edge; + } + } + else + { // insert seperate edges + if (((int)forward_edge.data.weight) != INVALID_EDGE_WEIGHT) + { + edges[edge++] = forward_edge; + } + if ((int)reverse_edge.data.weight != INVALID_EDGE_WEIGHT) + { + edges[edge++] = reverse_edge; + } + } } - // FIXME not sure if we need this - edges.shrink_to_fit(); - return edges; + util::Log() << "merged " << edges.size() - edge << " edges out of " << edges.size(); + edges.resize(edge); + + return ContractorGraph{number_of_nodes, edges}; } } // namespace contractor diff --git a/include/util/dynamic_graph.hpp b/include/util/dynamic_graph.hpp index bda95d74a..6bb891faf 100644 --- a/include/util/dynamic_graph.hpp +++ b/include/util/dynamic_graph.hpp @@ -66,6 +66,8 @@ template class DynamicGraph } }; + DynamicGraph() : DynamicGraph(0) {} + // Constructs an empty graph with a given number of nodes. explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0) { diff --git a/src/contractor/contractor.cpp b/src/contractor/contractor.cpp index c212ab2c9..cff8761aa 100644 --- a/src/contractor/contractor.cpp +++ b/src/contractor/contractor.cpp @@ -72,8 +72,7 @@ int Contractor::Run() util::DeallocatingVector contracted_edge_list; { // own scope to not keep the contractor around - GraphContractor graph_contractor(max_edge_id + 1, - adaptToContractorInput(std::move(edge_based_edge_list)), + GraphContractor graph_contractor(toContractorGraph(max_edge_id+1, std::move(edge_based_edge_list)), std::move(node_levels), std::move(node_weights)); graph_contractor.Run(config.core_factor); diff --git a/src/contractor/graph_contractor.cpp b/src/contractor/graph_contractor.cpp index 51706f932..51f83577d 100644 --- a/src/contractor/graph_contractor.cpp +++ b/src/contractor/graph_contractor.cpp @@ -5,87 +5,17 @@ namespace osrm namespace contractor { -GraphContractor::GraphContractor(int nodes, std::vector input_edge_list) - : GraphContractor(nodes, std::move(input_edge_list), {}, {}) +GraphContractor::GraphContractor(ContractorGraph graph_) + : GraphContractor(std::move(graph_), {}, {}) { } -GraphContractor::GraphContractor(int nodes, - std::vector edges, +GraphContractor::GraphContractor(ContractorGraph graph_, std::vector node_levels_, std::vector node_weights_) - : node_levels(std::move(node_levels_)), node_weights(std::move(node_weights_)) + : graph(std::move(graph_)), node_levels(std::move(node_levels_)), + node_weights(std::move(node_weights_)) { - tbb::parallel_sort(edges.begin(), edges.end()); - NodeID edge = 0; - for (NodeID i = 0; i < edges.size();) - { - const NodeID source = edges[i].source; - const NodeID target = edges[i].target; - const NodeID id = edges[i].data.id; - // remove eigenloops - if (source == target) - { - ++i; - continue; - } - ContractorEdge forward_edge; - ContractorEdge reverse_edge; - forward_edge.source = reverse_edge.source = source; - forward_edge.target = reverse_edge.target = target; - forward_edge.data.forward = reverse_edge.data.backward = true; - forward_edge.data.backward = reverse_edge.data.forward = false; - forward_edge.data.shortcut = reverse_edge.data.shortcut = false; - forward_edge.data.id = reverse_edge.data.id = id; - forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1; - forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT; - forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION; - // remove parallel edges - while (i < edges.size() && edges[i].source == source && edges[i].target == target) - { - if (edges[i].data.forward) - { - forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight); - forward_edge.data.duration = - std::min(edges[i].data.duration, forward_edge.data.duration); - } - if (edges[i].data.backward) - { - reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight); - reverse_edge.data.duration = - std::min(edges[i].data.duration, reverse_edge.data.duration); - } - ++i; - } - // merge edges (s,t) and (t,s) into bidirectional edge - if (forward_edge.data.weight == reverse_edge.data.weight) - { - if ((int)forward_edge.data.weight != INVALID_EDGE_WEIGHT) - { - forward_edge.data.backward = true; - edges[edge++] = forward_edge; - } - } - else - { // insert seperate edges - if (((int)forward_edge.data.weight) != INVALID_EDGE_WEIGHT) - { - edges[edge++] = forward_edge; - } - if ((int)reverse_edge.data.weight != INVALID_EDGE_WEIGHT) - { - edges[edge++] = reverse_edge; - } - } - } - util::Log() << "merged " << edges.size() - edge << " edges out of " << edges.size(); - edges.resize(edge); - contractor_graph = std::make_shared(nodes, edges); - edges.clear(); - edges.shrink_to_fit(); - - BOOST_ASSERT(0 == edges.capacity()); - util::Log() << "contractor finished initalization"; } /* Flush all data from the contraction to disc and reorder stuff for better locality */ @@ -107,7 +37,7 @@ void GraphContractor::FlushDataAndRebuildContractorGraph( orig_node_id_from_new_node_id_map.resize(remaining_nodes.size()); // this map gives the new IDs from the old ones, necessary to remap targets from the // remaining graph - const auto number_of_nodes = contractor_graph->GetNumberOfNodes(); + const auto number_of_nodes = graph.GetNumberOfNodes(); std::vector new_node_id_from_orig_id_map(number_of_nodes, SPECIAL_NODEID); for (const auto new_node_id : util::irange(0UL, remaining_nodes.size())) { @@ -127,12 +57,12 @@ void GraphContractor::FlushDataAndRebuildContractorGraph( node.id = new_node_id; } // walk over all nodes - for (const auto source : util::irange(0UL, contractor_graph->GetNumberOfNodes())) + for (const auto source : util::irange(0UL, graph.GetNumberOfNodes())) { - for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source)) + for (auto current_edge : graph.GetAdjacentEdgeRange(source)) { - ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(current_edge); - const NodeID target = contractor_graph->GetTarget(current_edge); + ContractorGraph::EdgeData &data = graph.GetEdgeData(current_edge); + const NodeID target = graph.GetTarget(current_edge); if (SPECIAL_NODEID == new_node_id_from_orig_id_map[source]) { external_edge_list.push_back({source, target, data}); @@ -158,14 +88,14 @@ void GraphContractor::FlushDataAndRebuildContractorGraph( // Delete old node_priorities vector node_weights.swap(new_node_weights); // old Graph is removed - contractor_graph.reset(); + graph = ContractorGraph{}; // create new graph tbb::parallel_sort(new_edge_set.begin(), new_edge_set.end()); - contractor_graph = std::make_shared(remaining_nodes.size(), new_edge_set); + graph = ContractorGraph{static_cast(remaining_nodes.size()), new_edge_set}; new_edge_set.clear(); // INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH! // reinitialize heaps and ThreadData objects with appropriate size - thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes(); + thread_data_list.number_of_nodes = graph.GetNumberOfNodes(); } void GraphContractor::Run(double core_factor) @@ -181,7 +111,7 @@ void GraphContractor::Run(double core_factor) const constexpr size_t NeighboursGrainSize = 1; const constexpr size_t DeleteGrainSize = 1; - const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes(); + const NodeID number_of_nodes = graph.GetNumberOfNodes(); ThreadDataContainer thread_data_list(number_of_nodes); @@ -340,11 +270,10 @@ void GraphContractor::Run(double core_factor) { for (const ContractorEdge &edge : data->inserted_edges) { - const EdgeID current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target); + const EdgeID current_edge_ID = graph.FindEdge(edge.source, edge.target); if (current_edge_ID != SPECIAL_EDGEID) { - ContractorGraph::EdgeData ¤t_data = - contractor_graph->GetEdgeData(current_edge_ID); + ContractorGraph::EdgeData ¤t_data = graph.GetEdgeData(current_edge_ID); if (current_data.shortcut && edge.data.forward == current_data.forward && edge.data.backward == current_data.backward) { @@ -357,7 +286,7 @@ void GraphContractor::Run(double core_factor) continue; } } - contractor_graph->InsertEdge(edge.source, edge.target, edge.data); + graph.InsertEdge(edge.source, edge.target, edge.data); } data->inserted_edges.clear(); } @@ -421,8 +350,8 @@ void GraphContractor::Run(double core_factor) is_core_node.clear(); } - util::Log() << "[core] " << remaining_nodes.size() << " nodes " - << contractor_graph->GetNumberOfEdges() << " edges."; + util::Log() << "[core] " << remaining_nodes.size() << " nodes " << graph.GetNumberOfEdges() + << " edges."; thread_data_list.data.clear(); } @@ -465,9 +394,9 @@ void GraphContractor::DeleteIncomingEdges(ContractorThreadData *data, const Node neighbours.clear(); // find all neighbours - for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) + for (auto e : graph.GetAdjacentEdgeRange(node)) { - const NodeID u = contractor_graph->GetTarget(e); + const NodeID u = graph.GetTarget(e); if (u != node) { neighbours.push_back(u); @@ -479,7 +408,7 @@ void GraphContractor::DeleteIncomingEdges(ContractorThreadData *data, const Node for (const auto i : util::irange(0, neighbours.size())) { - contractor_graph->DeleteEdgesTo(neighbours[i], node); + graph.DeleteEdgesTo(neighbours[i], node); } } @@ -492,9 +421,9 @@ bool GraphContractor::UpdateNodeNeighbours(std::vector &priorities, neighbours.clear(); // find all neighbours - for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) + for (auto e : graph.GetAdjacentEdgeRange(node)) { - const NodeID u = contractor_graph->GetTarget(e); + const NodeID u = graph.GetTarget(e); if (u == node) { continue; @@ -523,9 +452,9 @@ bool GraphContractor::IsNodeIndependent(const std::vector &priorities, std::vector &neighbours = data->neighbours; neighbours.clear(); - for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) + for (auto e : graph.GetAdjacentEdgeRange(node)) { - const NodeID target = contractor_graph->GetTarget(e); + const NodeID target = graph.GetTarget(e); if (node == target) { continue; @@ -552,9 +481,9 @@ bool GraphContractor::IsNodeIndependent(const std::vector &priorities, // examine all neighbours that are at most 2 hops away for (const NodeID u : neighbours) { - for (auto e : contractor_graph->GetAdjacentEdgeRange(u)) + for (auto e : graph.GetAdjacentEdgeRange(u)) { - const NodeID target = contractor_graph->GetTarget(e); + const NodeID target = graph.GetTarget(e); if (node == target) { continue;