Replace deallocation vector with std::vector and different merge algorithm

This commit is contained in:
Patrick Niklaus 2017-10-11 23:23:57 +00:00 committed by Patrick Niklaus
parent 69db219423
commit 9b87b8b7b1
5 changed files with 86 additions and 69 deletions

View File

@ -2,9 +2,17 @@
#define OSRM_CONTRACTOR_CONTRACTED_EDGE_CONTAINER_HPP #define OSRM_CONTRACTOR_CONTRACTED_EDGE_CONTAINER_HPP
#include "contractor/query_edge.hpp" #include "contractor/query_edge.hpp"
#include "util/deallocating_vector.hpp"
#include "util/integer_range.hpp"
#include "util/permutation.hpp"
#include <tbb/parallel_sort.h>
#include <algorithm>
#include <climits> #include <climits>
#include <cstdint>
#include <numeric>
#include <vector>
namespace osrm namespace osrm
{ {
@ -43,7 +51,7 @@ struct ContractedEdgeContainer
} }
public: public:
void Insert(util::DeallocatingVector<QueryEdge> new_edges) void Insert(std::vector<QueryEdge> new_edges)
{ {
BOOST_ASSERT(edges.size() == 0); BOOST_ASSERT(edges.size() == 0);
BOOST_ASSERT(flags.empty()); BOOST_ASSERT(flags.empty());
@ -52,80 +60,68 @@ struct ContractedEdgeContainer
flags.resize(edges.size(), ALL_FLAGS); flags.resize(edges.size(), ALL_FLAGS);
} }
void Merge(util::DeallocatingVector<QueryEdge> new_edges) void Merge(std::vector<QueryEdge> new_edges)
{ {
BOOST_ASSERT(index < sizeof(MergedFlags) * CHAR_BIT); BOOST_ASSERT(index < sizeof(MergedFlags) * CHAR_BIT);
const MergedFlags flag = 1 << index++; const MergedFlags flag = 1 << index++;
std::vector<MergedFlags> merged_flags; auto edge_iter = edges.cbegin();
merged_flags.reserve(flags.size() * 1.1); auto edge_end = edges.cend();
util::DeallocatingVector<QueryEdge> merged_edges;
merged_edges.reserve(edges.size() * 1.1);
auto flags_iter = flags.begin(); auto flags_iter = flags.begin();
// destructive iterators, this is single-pass only
// FIXME using dbegin() dend() will result in segfaults.
auto edges_iter = edges.dbegin();
auto edges_end = edges.dend();
auto new_edges_iter = new_edges.dbegin();
auto new_edges_end = new_edges.dend();
while (edges_iter != edges_end && new_edges_iter != new_edges_end) // Remove all edges that are contained in the old set of edges and set the appropriate flag.
auto new_end = std::remove_if(new_edges.begin(), new_edges.end(), [&](const auto &edge) {
// check if the new edge would be sorted before the currend old edge
// if so it is not contained yet in the set of old edges
if (edge_iter == edge_end || mergeCompare(edge, *edge_iter))
{ {
while (edges_iter != edges_end && mergeCompare(*edges_iter, *new_edges_iter)) return false;
}
// find the first old edge that is equal or greater then the new edge
while (edge_iter != edge_end && mergeCompare(*edge_iter, edge))
{ {
merged_edges.push_back(*edges_iter); BOOST_ASSERT(flags_iter != flags.end());
merged_flags.push_back(*flags_iter); edge_iter++;
edges_iter++;
flags_iter++; flags_iter++;
} }
if (edges_iter == edges_end) // all new edges will be sorted after the old edges
if (edge_iter == edge_end)
{ {
break; return false;
} }
while (new_edges_iter != new_edges_end && mergeCompare(*new_edges_iter, *edges_iter)) BOOST_ASSERT(edge_iter != edge_end);
if (mergable(edge, *edge_iter))
{ {
merged_edges.push_back(*new_edges_iter); *flags_iter = *flags_iter | flag;
merged_flags.push_back(flag); return true;
new_edges_iter++;
} }
BOOST_ASSERT(mergeCompare(edge, *edge_iter));
return false;
});
if (new_edges_iter == new_edges_end) // append new edges
{ edges.insert(edges.end(), new_edges.begin(), new_end);
break; auto edges_size = edges.size();
} auto new_edges_size = std::distance(new_edges.begin(), new_end);
BOOST_ASSERT(edges_size >= new_edges_size);
flags.resize(edges_size);
std::fill(flags.begin() + edges_size - new_edges_size, flags.end(), flag);
while (edges_iter != edges_end && new_edges_iter != new_edges_end && // enforce sorting for next merge step
mergable(*edges_iter, *new_edges_iter)) std::vector<unsigned> ordering(edges_size);
{ std::iota(ordering.begin(), ordering.end(), 0);
merged_edges.push_back(*edges_iter); tbb::parallel_sort(ordering.begin(), ordering.end(), [&](const auto lhs_idx, const auto rhs_idx) {
merged_flags.push_back(*flags_iter | flag); return mergeCompare(edges[lhs_idx], edges[rhs_idx]);
});
auto permutation = util::orderingToPermutation(ordering);
edges_iter++; util::inplacePermutation(edges.begin(), edges.end(), permutation);
flags_iter++; util::inplacePermutation(flags.begin(), flags.end(), permutation);
new_edges_iter++; BOOST_ASSERT(std::is_sorted(edges.begin(), edges.end(), mergeCompare));
}
}
while (edges_iter != edges_end)
{
BOOST_ASSERT(new_edges_iter == new_edges_end);
merged_edges.push_back(*edges_iter++);
merged_flags.push_back(*flags_iter++);
}
while (new_edges_iter != new_edges_end)
{
BOOST_ASSERT(edges_iter == edges_end);
merged_edges.push_back(*new_edges_iter++);
merged_flags.push_back(flag);
}
flags = std::move(merged_flags);
edges = std::move(merged_edges);
} }
auto MakeEdgeFilters() const auto MakeEdgeFilters() const
@ -145,7 +141,7 @@ struct ContractedEdgeContainer
std::size_t index = 0; std::size_t index = 0;
std::vector<MergedFlags> flags; std::vector<MergedFlags> flags;
util::DeallocatingVector<QueryEdge> edges; std::vector<QueryEdge> edges;
}; };
} }
} }

View File

@ -2,6 +2,7 @@
#define OSRM_CONTRACTOR_GRAPH_CONTRACTION_ADAPTORS_HPP_ #define OSRM_CONTRACTOR_GRAPH_CONTRACTION_ADAPTORS_HPP_
#include "contractor/contractor_graph.hpp" #include "contractor/contractor_graph.hpp"
#include "util/log.hpp" #include "util/log.hpp"
#include "util/percent.hpp" #include "util/percent.hpp"
@ -125,9 +126,10 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
return ContractorGraph{number_of_nodes, edges}; return ContractorGraph{number_of_nodes, edges};
} }
template <class Edge, typename GraphT> inline util::DeallocatingVector<Edge> toEdges(GraphT graph) template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT graph)
{ {
util::DeallocatingVector<Edge> edges; std::vector<Edge> edges;
edges.reserve(graph.GetNumberOfEdges());
util::UnbufferedLog log; util::UnbufferedLog log;
log << "Getting edges of minimized graph "; log << "Getting edges of minimized graph ";
@ -163,6 +165,7 @@ template <class Edge, typename GraphT> inline util::DeallocatingVector<Edge> toE
tbb::parallel_sort(edges.begin(), edges.end()); tbb::parallel_sort(edges.begin(), edges.end());
auto new_end = std::unique(edges.begin(), edges.end()); auto new_end = std::unique(edges.begin(), edges.end());
edges.resize(new_end - edges.begin()); edges.resize(new_end - edges.begin());
edges.shrink_to_fit();
return edges; return edges;
} }

View File

@ -23,7 +23,15 @@ void inplacePermutation(RandomAccesIterator begin,
for (auto index : util::irange<IndexT>(0, size)) for (auto index : util::irange<IndexT>(0, size))
{ {
if (was_replaced[index]) if (was_replaced[index])
{
continue; continue;
}
if (old_to_new[index] == index)
{
was_replaced[index] = true;
continue;
}
// iterate over a cycle in the permutation // iterate over a cycle in the permutation
auto buffer = begin[index]; auto buffer = begin[index];
@ -38,6 +46,18 @@ void inplacePermutation(RandomAccesIterator begin,
std::swap(buffer, begin[index]); std::swap(buffer, begin[index]);
} }
} }
template <typename IndexT>
std::vector<IndexT> orderingToPermutation(const std::vector<IndexT> &ordering)
{
std::vector<std::uint32_t> permutation(ordering.size());
for (auto index : util::irange<std::uint32_t>(0, ordering.size()))
permutation[ordering[index]] = index;
return permutation;
}
} }
} }

View File

@ -1,5 +1,7 @@
#include "partition/renumber.hpp" #include "partition/renumber.hpp"
#include "util/permutation.hpp"
#include <tbb/parallel_sort.h> #include <tbb/parallel_sort.h>
namespace osrm namespace osrm
@ -64,11 +66,7 @@ std::vector<std::uint32_t> makePermutation(const DynamicEdgeBasedGraph &graph,
return border_level[lhs] > border_level[rhs]; return border_level[lhs] > border_level[rhs];
}); });
std::vector<std::uint32_t> permutation(ordering.size()); return util::orderingToPermutation(ordering);
for (auto index : util::irange<std::uint32_t>(0, ordering.size()))
permutation[ordering[index]] = index;
return permutation;
} }
} }
} }

View File

@ -35,7 +35,7 @@ BOOST_AUTO_TEST_CASE(merge_edge_of_multiple_graph)
{ {
ContractedEdgeContainer container; ContractedEdgeContainer container;
util::DeallocatingVector<QueryEdge> edges; std::vector<QueryEdge> edges;
edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}}); edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}}); edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
edges.push_back(QueryEdge{2, 0, {3, false, 3, 6, false, true}}); edges.push_back(QueryEdge{2, 0, {3, false, 3, 6, false, true}});
@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(merge_edge_of_multiple_graph)
edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}}); edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
container.Merge(edges); container.Merge(edges);
util::DeallocatingVector<QueryEdge> reference_edges; std::vector<QueryEdge> reference_edges;
reference_edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}}); reference_edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}}); reference_edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}}); reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE(merge_edge_of_multiple_disjoint_graph)
{ {
ContractedEdgeContainer container; ContractedEdgeContainer container;
util::DeallocatingVector<QueryEdge> edges; std::vector<QueryEdge> edges;
edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}}); edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}}); edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
edges.push_back(QueryEdge{2, 0, {3, false, 12, 24, false, true}}); edges.push_back(QueryEdge{2, 0, {3, false, 12, 24, false, true}});
@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE(merge_edge_of_multiple_disjoint_graph)
edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}}); edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
container.Merge(edges); container.Merge(edges);
util::DeallocatingVector<QueryEdge> reference_edges; std::vector<QueryEdge> reference_edges;
reference_edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}}); reference_edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}}); reference_edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}}); reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});