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
#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 <cstdint>
#include <numeric>
#include <vector>
namespace osrm
{
@ -43,7 +51,7 @@ struct ContractedEdgeContainer
}
public:
void Insert(util::DeallocatingVector<QueryEdge> new_edges)
void Insert(std::vector<QueryEdge> new_edges)
{
BOOST_ASSERT(edges.size() == 0);
BOOST_ASSERT(flags.empty());
@ -52,80 +60,68 @@ struct ContractedEdgeContainer
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);
const MergedFlags flag = 1 << index++;
std::vector<MergedFlags> merged_flags;
merged_flags.reserve(flags.size() * 1.1);
util::DeallocatingVector<QueryEdge> merged_edges;
merged_edges.reserve(edges.size() * 1.1);
auto edge_iter = edges.cbegin();
auto edge_end = edges.cend();
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)
{
while (edges_iter != edges_end && mergeCompare(*edges_iter, *new_edges_iter))
// 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))
{
merged_edges.push_back(*edges_iter);
merged_flags.push_back(*flags_iter);
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))
{
BOOST_ASSERT(flags_iter != flags.end());
edge_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);
merged_flags.push_back(flag);
new_edges_iter++;
*flags_iter = *flags_iter | flag;
return true;
}
BOOST_ASSERT(mergeCompare(edge, *edge_iter));
return false;
});
if (new_edges_iter == new_edges_end)
{
break;
}
// append new edges
edges.insert(edges.end(), new_edges.begin(), new_end);
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 &&
mergable(*edges_iter, *new_edges_iter))
{
merged_edges.push_back(*edges_iter);
merged_flags.push_back(*flags_iter | flag);
// enforce sorting for next merge step
std::vector<unsigned> ordering(edges_size);
std::iota(ordering.begin(), ordering.end(), 0);
tbb::parallel_sort(ordering.begin(), ordering.end(), [&](const auto lhs_idx, const auto rhs_idx) {
return mergeCompare(edges[lhs_idx], edges[rhs_idx]);
});
auto permutation = util::orderingToPermutation(ordering);
edges_iter++;
flags_iter++;
new_edges_iter++;
}
}
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);
util::inplacePermutation(edges.begin(), edges.end(), permutation);
util::inplacePermutation(flags.begin(), flags.end(), permutation);
BOOST_ASSERT(std::is_sorted(edges.begin(), edges.end(), mergeCompare));
}
auto MakeEdgeFilters() const
@ -145,7 +141,7 @@ struct ContractedEdgeContainer
std::size_t index = 0;
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_
#include "contractor/contractor_graph.hpp"
#include "util/log.hpp"
#include "util/percent.hpp"
@ -125,9 +126,10 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
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;
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());
auto new_end = std::unique(edges.begin(), edges.end());
edges.resize(new_end - edges.begin());
edges.shrink_to_fit();
return edges;
}

View File

@ -23,7 +23,15 @@ void inplacePermutation(RandomAccesIterator begin,
for (auto index : util::irange<IndexT>(0, size))
{
if (was_replaced[index])
{
continue;
}
if (old_to_new[index] == index)
{
was_replaced[index] = true;
continue;
}
// iterate over a cycle in the permutation
auto buffer = begin[index];
@ -38,6 +46,18 @@ void inplacePermutation(RandomAccesIterator begin,
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 "util/permutation.hpp"
#include <tbb/parallel_sort.h>
namespace osrm
@ -64,11 +66,7 @@ std::vector<std::uint32_t> makePermutation(const DynamicEdgeBasedGraph &graph,
return border_level[lhs] > border_level[rhs];
});
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;
return util::orderingToPermutation(ordering);
}
}
}

View File

@ -35,7 +35,7 @@ BOOST_AUTO_TEST_CASE(merge_edge_of_multiple_graph)
{
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{1, 2, {2, false, 3, 6, true, false}});
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}});
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{1, 2, {2, 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;
util::DeallocatingVector<QueryEdge> edges;
std::vector<QueryEdge> edges;
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{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}});
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{1, 2, {2, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});