Precompute accumulated segment data

This commit is contained in:
Patrick Niklaus 2017-03-15 01:03:55 +00:00 committed by Patrick Niklaus
parent 864543b023
commit 4684a498c4

View File

@ -345,12 +345,6 @@ updateSegmentData(const UpdaterConfig &config,
} }
} }
tbb::parallel_sort(updated_segments.begin(),
updated_segments.end(),
[](const GeometryID lhs, const GeometryID rhs) {
return std::tie(lhs.id, lhs.forward) < std::tie(rhs.id, rhs.forward);
});
return updated_segments; return updated_segments;
} }
@ -543,58 +537,35 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
util::Log() << "Updating segment data took " << TIMER_MSEC(segment) << "ms."; util::Log() << "Updating segment data took " << TIMER_MSEC(segment) << "ms.";
} }
std::vector<std::uint64_t> updated_turn_penalties;
if (update_turn_penalties) if (update_turn_penalties)
{ {
auto turn_penalty_lookup = csv::readTurnValues(config.turn_penalty_lookup_paths); auto turn_penalty_lookup = csv::readTurnValues(config.turn_penalty_lookup_paths);
updated_turn_penalties = updateTurnPenalties(config, auto updated_turn_penalties = updateTurnPenalties(config,
profile_properties, profile_properties,
turn_penalty_lookup, turn_penalty_lookup,
turn_weight_penalties, turn_weight_penalties,
turn_duration_penalties); turn_duration_penalties);
} // we need to re-compute all edges that have updated turn penalties.
// this marks it for re-computation
// Mapped file pointers for edge-based graph edges std::transform(updated_turn_penalties.begin(),
auto edge_based_edge_ptr = reinterpret_cast<const extractor::EdgeBasedEdge *>( updated_turn_penalties.end(),
reinterpret_cast<char *>(edge_based_graph_region.get_address()) + std::back_inserter(updated_segments),
sizeof(EdgeBasedGraphHeader)); [&edge_data](const std::uint64_t edge_index) {
BOOST_ASSERT(is_aligned<extractor::EdgeBasedEdge>(edge_based_edge_ptr)); return edge_data[edge_index].via_geometry;
for (std::uint64_t edge_index = 0; edge_index < graph_header.number_of_edges; ++edge_index)
{
// Make a copy of the data from the memory map
extractor::EdgeBasedEdge inbuffer = edge_based_edge_ptr[edge_index];
bool needs_update = update_turn_penalties;
if (update_edge_weights)
{
const auto geometry_id = edge_data[edge_index].via_geometry;
auto updated_iter = std::lower_bound(updated_segments.begin(),
updated_segments.end(),
geometry_id,
[](const GeometryID lhs, const GeometryID rhs) {
return std::tie(lhs.id, lhs.forward) <
std::tie(rhs.id, rhs.forward);
}); });
if (updated_iter == updated_segments.end() || updated_iter->id != geometry_id.id ||
updated_iter->forward != geometry_id.forward)
{
needs_update = update_turn_penalties;
}
else
{
needs_update = true;
}
} }
if (needs_update) tbb::parallel_sort(updated_segments.begin(),
{ updated_segments.end(),
// Find a segment with zero speed and simultaneously compute the new edge weight [](const GeometryID lhs, const GeometryID rhs) {
return std::tie(lhs.id, lhs.forward) < std::tie(rhs.id, rhs.forward);
});
using WeightAndDuration = std::tuple<EdgeWeight, EdgeWeight>;
const auto compute_new_weight_and_duration =
[&](const GeometryID geometry_id) -> WeightAndDuration {
EdgeWeight new_weight = 0; EdgeWeight new_weight = 0;
EdgeWeight new_duration = 0; EdgeWeight new_duration = 0;
bool skip_edge = false;
const auto geometry_id = edge_data[edge_index].via_geometry;
if (geometry_id.forward) if (geometry_id.forward)
{ {
const auto weights = segment_data.GetForwardWeights(geometry_id.id); const auto weights = segment_data.GetForwardWeights(geometry_id.id);
@ -602,7 +573,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
{ {
if (weight == INVALID_EDGE_WEIGHT) if (weight == INVALID_EDGE_WEIGHT)
{ {
skip_edge = true; new_weight = INVALID_EDGE_WEIGHT;
break; break;
} }
new_weight += weight; new_weight += weight;
@ -617,7 +588,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
{ {
if (weight == INVALID_EDGE_WEIGHT) if (weight == INVALID_EDGE_WEIGHT)
{ {
skip_edge = true; new_weight = INVALID_EDGE_WEIGHT;
break; break;
} }
new_weight += weight; new_weight += weight;
@ -625,6 +596,48 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
const auto durations = segment_data.GetReverseDurations(geometry_id.id); const auto durations = segment_data.GetReverseDurations(geometry_id.id);
new_duration = std::accumulate(durations.begin(), durations.end(), 0); new_duration = std::accumulate(durations.begin(), durations.end(), 0);
} }
return std::make_tuple(new_weight, new_duration);
};
std::vector<WeightAndDuration> accumulated_segment_data(updated_segments.size());
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, updated_segments.size()),
[&](const tbb::blocked_range<std::size_t> &range) {
for (auto index = range.begin(); index < range.end(); ++index)
{
accumulated_segment_data[index] =
compute_new_weight_and_duration(updated_segments[index]);
}
});
// Mapped file pointers for edge-based graph edges
auto edge_based_edge_ptr = reinterpret_cast<const extractor::EdgeBasedEdge *>(
reinterpret_cast<char *>(edge_based_graph_region.get_address()) +
sizeof(EdgeBasedGraphHeader));
BOOST_ASSERT(is_aligned<extractor::EdgeBasedEdge>(edge_based_edge_ptr));
for (std::uint64_t edge_index = 0; edge_index < graph_header.number_of_edges; ++edge_index)
{
// Make a copy of the data from the memory map
extractor::EdgeBasedEdge inbuffer = edge_based_edge_ptr[edge_index];
if (updated_segments.size() > 0)
{
const auto geometry_id = edge_data[edge_index].via_geometry;
auto updated_iter = std::lower_bound(updated_segments.begin(),
updated_segments.end(),
geometry_id,
[](const GeometryID lhs, const GeometryID rhs) {
return std::tie(lhs.id, lhs.forward) <
std::tie(rhs.id, rhs.forward);
});
if (updated_iter != updated_segments.end() && updated_iter->id == geometry_id.id &&
updated_iter->forward == geometry_id.forward)
{
// Find a segment with zero speed and simultaneously compute the new edge weight
EdgeWeight new_weight;
EdgeWeight new_duration;
std::tie(new_weight, new_duration) =
accumulated_segment_data[updated_iter - updated_segments.begin()];
// Update the node-weight cache. This is the weight of the edge-based-node only, // Update the node-weight cache. This is the weight of the edge-based-node only,
// it doesn't include the turn. We may visit the same node multiple times, but // it doesn't include the turn. We may visit the same node multiple times, but
@ -634,7 +647,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
// We found a zero-speed edge, so we'll skip this whole edge-based-edge which // We found a zero-speed edge, so we'll skip this whole edge-based-edge which
// effectively removes it from the routing network. // effectively removes it from the routing network.
if (skip_edge) if (new_weight == INVALID_EDGE_WEIGHT)
continue; continue;
// Get the turn penalty and update to the new value if required // Get the turn penalty and update to the new value if required
@ -662,6 +675,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
inbuffer.data.weight = new_weight + turn_weight_penalty; inbuffer.data.weight = new_weight + turn_weight_penalty;
inbuffer.data.duration = new_duration + turn_duration_penalty; inbuffer.data.duration = new_duration + turn_duration_penalty;
} }
}
edge_based_edge_list.emplace_back(std::move(inbuffer)); edge_based_edge_list.emplace_back(std::move(inbuffer));
} }