Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8cd40b9e90 | |||
| 45df8568b6 | |||
| 0da041477b | |||
| 272ea9b92e | |||
| 571681d019 | |||
| 9b614c6057 | |||
| 721f319909 |
@@ -5,7 +5,8 @@
|
|||||||
#include "partition/multi_level_partition.hpp"
|
#include "partition/multi_level_partition.hpp"
|
||||||
#include "util/binary_heap.hpp"
|
#include "util/binary_heap.hpp"
|
||||||
|
|
||||||
#include <boost/thread/tss.hpp>
|
#include <tbb/enumerable_thread_specific.h>
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@@ -15,12 +16,22 @@ namespace customizer
|
|||||||
|
|
||||||
class CellCustomizer
|
class CellCustomizer
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
struct HeapData
|
||||||
|
{
|
||||||
|
bool from_clique;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Heap =
|
||||||
|
util::BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::ArrayStorage<NodeID, int>>;
|
||||||
|
using HeapPtr = tbb::enumerable_thread_specific<Heap>;
|
||||||
|
|
||||||
CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
|
CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
|
||||||
|
|
||||||
template <typename GraphT>
|
template <typename GraphT>
|
||||||
void Customize(const GraphT &graph, partition::CellStorage &cells, LevelID level, CellID id)
|
void Customize(
|
||||||
|
const GraphT &graph, Heap &heap, partition::CellStorage &cells, LevelID level, CellID id)
|
||||||
{
|
{
|
||||||
auto cell = cells.GetCell(level, id);
|
auto cell = cells.GetCell(level, id);
|
||||||
auto destinations = cell.GetDestinationNodes();
|
auto destinations = cell.GetDestinationNodes();
|
||||||
@@ -29,8 +40,8 @@ class CellCustomizer
|
|||||||
for (auto source : cell.GetSourceNodes())
|
for (auto source : cell.GetSourceNodes())
|
||||||
{
|
{
|
||||||
std::unordered_set<NodeID> destinations_set(destinations.begin(), destinations.end());
|
std::unordered_set<NodeID> destinations_set(destinations.begin(), destinations.end());
|
||||||
Heap heap(graph.GetNumberOfNodes());
|
heap.Clear();
|
||||||
heap.Insert(source, 0, {});
|
heap.Insert(source, 0, {false});
|
||||||
|
|
||||||
// explore search space
|
// explore search space
|
||||||
while (!heap.Empty() && !destinations_set.empty())
|
while (!heap.Empty() && !destinations_set.empty())
|
||||||
@@ -60,26 +71,23 @@ class CellCustomizer
|
|||||||
|
|
||||||
template <typename GraphT> void Customize(const GraphT &graph, partition::CellStorage &cells)
|
template <typename GraphT> void Customize(const GraphT &graph, partition::CellStorage &cells)
|
||||||
{
|
{
|
||||||
|
Heap heap_exemplar(graph.GetNumberOfNodes());
|
||||||
|
HeapPtr heaps(heap_exemplar);
|
||||||
|
|
||||||
for (std::size_t level = 1; level < partition.GetNumberOfLevels(); ++level)
|
for (std::size_t level = 1; level < partition.GetNumberOfLevels(); ++level)
|
||||||
{
|
{
|
||||||
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, partition.GetNumberOfCells(level)),
|
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, partition.GetNumberOfCells(level)),
|
||||||
[&](const tbb::blocked_range<std::size_t> &range) {
|
[&](const tbb::blocked_range<std::size_t> &range) {
|
||||||
|
auto &heap = heaps.local();
|
||||||
for (auto id = range.begin(), end = range.end(); id != end; ++id)
|
for (auto id = range.begin(), end = range.end(); id != end; ++id)
|
||||||
{
|
{
|
||||||
Customize(graph, cells, level, id);
|
Customize(graph, heap, cells, level, id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct HeapData
|
|
||||||
{
|
|
||||||
};
|
|
||||||
using Heap = util::
|
|
||||||
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
|
||||||
using HeapPtr = boost::thread_specific_ptr<Heap>;
|
|
||||||
|
|
||||||
template <bool first_level, typename GraphT>
|
template <bool first_level, typename GraphT>
|
||||||
void RelaxNode(const GraphT &graph,
|
void RelaxNode(const GraphT &graph,
|
||||||
const partition::CellStorage &cells,
|
const partition::CellStorage &cells,
|
||||||
@@ -88,29 +96,42 @@ class CellCustomizer
|
|||||||
NodeID node,
|
NodeID node,
|
||||||
EdgeWeight weight) const
|
EdgeWeight weight) const
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(heap.WasInserted(node));
|
||||||
|
|
||||||
if (!first_level)
|
if (!first_level)
|
||||||
{
|
{
|
||||||
// Relax sub-cell nodes
|
// if we reaches this node from a clique arc we don't need to scan
|
||||||
auto subcell_id = partition.GetCell(level - 1, node);
|
// the clique arcs again because of the triangle inequality
|
||||||
auto subcell = cells.GetCell(level - 1, subcell_id);
|
//
|
||||||
auto subcell_destination = subcell.GetDestinationNodes().begin();
|
// d(parent, node) + d(node, v) >= d(parent, v)
|
||||||
for (auto subcell_weight : subcell.GetOutWeight(node))
|
//
|
||||||
|
// And if there is a path (parent, node, v) there must also be a
|
||||||
|
// clique arc (parent, v) with d(parent, v).
|
||||||
|
if (!heap.GetData(node).from_clique)
|
||||||
{
|
{
|
||||||
if (subcell_weight != INVALID_EDGE_WEIGHT)
|
// Relax sub-cell nodes
|
||||||
|
auto subcell_id = partition.GetCell(level - 1, node);
|
||||||
|
auto subcell = cells.GetCell(level - 1, subcell_id);
|
||||||
|
auto subcell_destination = subcell.GetDestinationNodes().begin();
|
||||||
|
for (auto subcell_weight : subcell.GetOutWeight(node))
|
||||||
{
|
{
|
||||||
const NodeID to = *subcell_destination;
|
if (subcell_weight != INVALID_EDGE_WEIGHT)
|
||||||
const EdgeWeight to_weight = subcell_weight + weight;
|
|
||||||
if (!heap.WasInserted(to))
|
|
||||||
{
|
{
|
||||||
heap.Insert(to, to_weight, {});
|
const NodeID to = *subcell_destination;
|
||||||
|
const EdgeWeight to_weight = subcell_weight + weight;
|
||||||
|
if (!heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
heap.Insert(to, to_weight, {true});
|
||||||
|
}
|
||||||
|
else if (to_weight < heap.GetKey(to))
|
||||||
|
{
|
||||||
|
heap.DecreaseKey(to, to_weight);
|
||||||
|
heap.GetData(to).from_clique = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (to_weight < heap.GetKey(to))
|
|
||||||
{
|
|
||||||
heap.DecreaseKey(to, to_weight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++subcell_destination;
|
++subcell_destination;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,11 +147,12 @@ class CellCustomizer
|
|||||||
const EdgeWeight to_weight = data.weight + weight;
|
const EdgeWeight to_weight = data.weight + weight;
|
||||||
if (!heap.WasInserted(to))
|
if (!heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
heap.Insert(to, to_weight, {});
|
heap.Insert(to, to_weight, {false});
|
||||||
}
|
}
|
||||||
else if (to_weight < heap.GetKey(to))
|
else if (to_weight < heap.GetKey(to))
|
||||||
{
|
{
|
||||||
heap.DecreaseKey(to, to_weight);
|
heap.DecreaseKey(to, to_weight);
|
||||||
|
heap.GetData(to).from_clique = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,48 @@ namespace osrm
|
|||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
|
|
||||||
|
template <typename NodeID, typename Key> class GenerationArrayStorage
|
||||||
|
{
|
||||||
|
using GenerationCounter = std::uint16_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GenerationArrayStorage(std::size_t size)
|
||||||
|
: positions(size, 0), generation(1), generations(size, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Key &operator[](NodeID node)
|
||||||
|
{
|
||||||
|
generation[node] = generation;
|
||||||
|
return positions[node];
|
||||||
|
}
|
||||||
|
|
||||||
|
Key peek_index(const NodeID node) const
|
||||||
|
{
|
||||||
|
if (generations[node] < generation)
|
||||||
|
{
|
||||||
|
return std::numeric_limits<Key>::max();
|
||||||
|
}
|
||||||
|
return positions[node];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
generation++;
|
||||||
|
// if generation overflows we end up at 0 again and need to clear the vector
|
||||||
|
if (generation == 0)
|
||||||
|
{
|
||||||
|
generation = 1;
|
||||||
|
std::fill(generations.begin(), generations.end(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GenerationCounter generation;
|
||||||
|
std::vector<GenerationCounter> generations;
|
||||||
|
std::vector<Key> positions;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename NodeID, typename Key> class ArrayStorage
|
template <typename NodeID, typename Key> class ArrayStorage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -92,10 +134,6 @@ template <typename NodeID,
|
|||||||
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
||||||
class BinaryHeap
|
class BinaryHeap
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
BinaryHeap(const BinaryHeap &right);
|
|
||||||
void operator=(const BinaryHeap &right);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using WeightType = Weight;
|
using WeightType = Weight;
|
||||||
using DataType = Data;
|
using DataType = Data;
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "osrm",
|
"name": "osrm",
|
||||||
"version": "5.7.0-latest.3",
|
"version": "5.7.0-latest.4",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ BOOST_AUTO_TEST_CASE(two_level_test)
|
|||||||
|
|
||||||
CellStorage storage(mlp, graph);
|
CellStorage storage(mlp, graph);
|
||||||
CellCustomizer customizer(mlp);
|
CellCustomizer customizer(mlp);
|
||||||
|
CellCustomizer::Heap heap(graph.GetNumberOfNodes());
|
||||||
|
|
||||||
auto cell_1_0 = storage.GetCell(1, 0);
|
auto cell_1_0 = storage.GetCell(1, 0);
|
||||||
auto cell_1_1 = storage.GetCell(1, 1);
|
auto cell_1_1 = storage.GetCell(1, 1);
|
||||||
@@ -80,8 +81,8 @@ BOOST_AUTO_TEST_CASE(two_level_test)
|
|||||||
REQUIRE_SIZE_RANGE(cell_1_1.GetOutWeight(2), 2);
|
REQUIRE_SIZE_RANGE(cell_1_1.GetOutWeight(2), 2);
|
||||||
REQUIRE_SIZE_RANGE(cell_1_1.GetInWeight(3), 2);
|
REQUIRE_SIZE_RANGE(cell_1_1.GetInWeight(3), 2);
|
||||||
|
|
||||||
customizer.Customize(graph, storage, 1, 0);
|
customizer.Customize(graph, heap, storage, 1, 0);
|
||||||
customizer.Customize(graph, storage, 1, 1);
|
customizer.Customize(graph, heap, storage, 1, 1);
|
||||||
|
|
||||||
// cell 0
|
// cell 0
|
||||||
// check row source -> destination
|
// check row source -> destination
|
||||||
@@ -203,14 +204,15 @@ BOOST_AUTO_TEST_CASE(four_levels_test)
|
|||||||
REQUIRE_SIZE_RANGE(cell_3_0.GetDestinationNodes(), 0);
|
REQUIRE_SIZE_RANGE(cell_3_0.GetDestinationNodes(), 0);
|
||||||
|
|
||||||
CellCustomizer customizer(mlp);
|
CellCustomizer customizer(mlp);
|
||||||
|
CellCustomizer::Heap heap(graph.GetNumberOfNodes());
|
||||||
|
|
||||||
customizer.Customize(graph, storage, 1, 0);
|
customizer.Customize(graph, heap, storage, 1, 0);
|
||||||
customizer.Customize(graph, storage, 1, 1);
|
customizer.Customize(graph, heap, storage, 1, 1);
|
||||||
customizer.Customize(graph, storage, 1, 2);
|
customizer.Customize(graph, heap, storage, 1, 2);
|
||||||
customizer.Customize(graph, storage, 1, 3);
|
customizer.Customize(graph, heap, storage, 1, 3);
|
||||||
|
|
||||||
customizer.Customize(graph, storage, 2, 0);
|
customizer.Customize(graph, heap, storage, 2, 0);
|
||||||
customizer.Customize(graph, storage, 2, 1);
|
customizer.Customize(graph, heap, storage, 2, 1);
|
||||||
|
|
||||||
// level 1
|
// level 1
|
||||||
// cell 0
|
// cell 0
|
||||||
|
|||||||
Reference in New Issue
Block a user