Skip to content

Commit

Permalink
use unpacking on distance and templatize the cache
Browse files Browse the repository at this point in the history
  • Loading branch information
ghoshkaj committed May 5, 2018
1 parent fbba23e commit 144c4d6
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 170 deletions.
88 changes: 7 additions & 81 deletions features/testbot/distance_matrix.feature
Original file line number Diff line number Diff line change
Expand Up @@ -25,80 +25,6 @@ Feature: Basic Distance Matrix
Given the query options
| exclude | toll |

Scenario: Testbot - Travel time matrix of minimal network with excludes
Given the query options
| exclude | toll |

Given the node map
"""
a b
c d
"""

And the ways
| nodes | highway | toll | # |
| ab | motorway | | not drivable for exclude=motorway |
| cd | primary | | always drivable |
| ac | highway | yes | not drivable for exclude=motorway exclude=toll and exclude=motorway,toll |
| bd | highway | yes | not drivable for exclude=motorway exclude=toll |

When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 15 | | |
| b | 15 | 0 | | |
| c | | | 0 | 10 |
| d | | | 10 | 0 |

Scenario: Testbot - Travel time matrix of minimal network with different exclude
Given the query options
| exclude | motorway |

Given the node map
"""
a b
c d
"""

And the ways
| nodes | highway | toll | # |
| ab | motorway | | not drivable for exclude=motorway |
| cd | primary | | always drivable |
| ac | highway | yes | not drivable for exclude=motorway exclude=toll and exclude=motorway,toll |
| bd | highway | yes | not drivable for exclude=motorway exclude=toll |


When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 40 | 15 | 25 |
| b | 40 | 0 | 25 | 15 |
| c | 15 | 25 | 0 | 10 |
| d | 25 | 15 | 10 | 0 |

Scenario: Testbot - Travel time matrix of minimal network with excludes combination
Given the query options
| exclude | motorway,toll |

Given the node map
"""
a b
c d
"""

And the ways
| nodes | highway | toll | # |
| ab | motorway | | not drivable for exclude=motorway |
| cd | primary | | always drivable |
| ac | highway | yes | not drivable for exclude=motorway exclude=toll and exclude=motorway,toll |
| bd | highway | yes | not drivable for exclude=motorway exclude=toll |

When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 0 | 10 |
| b | 10 | 0 | 10 | 0 |
| c | 0 | 10 | 0 | 10 |
| d | 10 | 0 | 10 | 0 |

Scenario: Testbot - Travel time matrix with different way speeds
Given the node map
"""
a b
Expand Down Expand Up @@ -404,10 +330,10 @@ Feature: Basic Distance Matrix

When I request a travel distance matrix I should get
| | f | g | h | i |
| f | 0 | 300+-2 | 0 | 300+-2 |
| g | 300+-2 | 0 | 300+-2 | 0 |
| h | 0 | 300+-2 | 0 | 300+-2 |
| i | 300+-2 | 0 | 300+-2 | 0 |
| f | 0 | 300+-3 | 0 | 300+-3 |
| g | 300+-3 | 0 | 300+-3 | 0 |
| h | 0 | 300+-3 | 0 | 300+-3 |
| i | 300+-3 | 0 | 300+-3 | 0 |

Scenario: Testbot - Travel distance matrix with loops
Given the node map
Expand All @@ -426,9 +352,9 @@ Feature: Basic Distance Matrix
When I request a travel distance matrix I should get
| | 1 | 2 | 3 | 4 |
| 1 | 0 | 100+-1 | 400+-1 | 500+-1 |
| 2 | 700+-1 | 0 | 300+-1 | 400+-1 |
| 2 | 700+-2 | 0 | 300+-2 | 400+-1 |
| 3 | 400+-1 | 500+-1 | 0 | 100+-1 |
| 4 | 300+-1 | 400+-1 | 700+-1 | 0 |
| 4 | 300+-2 | 400+-1 | 700+-3 | 0 |


Scenario: Testbot - Travel distance matrix based on segment durations
Expand Down Expand Up @@ -570,4 +496,4 @@ Feature: Basic Distance Matrix

When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 1000+-3 | 2000+-3 | 3000+-3 |
| a | 0 | 1000+-3 | 2000+-3 | 3000+-3 |
2 changes: 0 additions & 2 deletions include/engine/routing_algorithms/routing_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ void annotatePath(const FacadeT &facade,
const auto geometry_index = facade.GetGeometryIndex(node_id);
get_segment_geometry(geometry_index);


BOOST_ASSERT(id_vector.size() > 0);
BOOST_ASSERT(datasource_vector.size() > 0);
BOOST_ASSERT(weight_vector.size() + 1 == id_vector.size());
Expand Down Expand Up @@ -407,7 +406,6 @@ InternalRouteResult extractRoute(const DataFacade<AlgorithmT> &facade,
return raw_route_data;
}


template <typename FacadeT> EdgeDistance computeEdgeDistance(const FacadeT &facade, NodeID node_id)
{
const auto geometry_index = facade.GetGeometryIndex(node_id);
Expand Down
21 changes: 11 additions & 10 deletions include/engine/routing_algorithms/routing_base_ch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,12 @@ void unpackPath(const DataFacade<Algorithm> &facade,
}
}
}

template <typename BidirectionalIterator>
EdgeDistance calculateEBGNodeDuration(const DataFacade<Algorithm> &facade,
BidirectionalIterator packed_path_begin,
BidirectionalIterator packed_path_end,
UnpackingCache &unpacking_cache)
EdgeDuration calculateEBGNodeDuration(const DataFacade<Algorithm> &facade,
BidirectionalIterator packed_path_begin,
BidirectionalIterator packed_path_end,
UnpackingCache<EdgeDuration> &unpacking_cache)
{
// Make sure we have at least something to unpack
if (packed_path_begin == packed_path_end ||
Expand Down Expand Up @@ -324,7 +325,7 @@ EdgeDistance calculateEBGNodeDuration(const DataFacade<Algorithm> &facade,
if (unpacking_cache.IsEdgeInCache(std::make_tuple(
std::get<0>(edge), std::get<1>(edge), facade.GetExcludeIndex())))
{
EdgeDuration duration = unpacking_cache.GetDuration(std::make_tuple(
EdgeDuration duration = unpacking_cache.GetAnnotation(std::make_tuple(
std::get<0>(edge), std::get<1>(edge), facade.GetExcludeIndex()));
duration_stack.emplace(duration);
}
Expand Down Expand Up @@ -404,19 +405,19 @@ EdgeDistance calculateEBGNodeDuration(const DataFacade<Algorithm> &facade,
return total_duration;
}


template <typename BidirectionalIterator>
EdgeDistance calculateEBGNodeDistance(const DataFacade<Algorithm> &facade,
BidirectionalIterator packed_path_begin,
BidirectionalIterator packed_path_end,
UnpackingCache &unpacking_cache)
BidirectionalIterator packed_path_begin,
BidirectionalIterator packed_path_end,
UnpackingCache<EdgeDistance> &unpacking_cache)
{
// Make sure we have at least something to unpack
if (packed_path_begin == packed_path_end ||
std::distance(packed_path_begin, packed_path_end) <= 1)
return 0;

std::stack<std::tuple<NodeID, NodeID, bool>> recursion_stack;

std::stack<EdgeDistance> distance_stack;
// We have to push the path in reverse order onto the stack because it's LIFO.
for (auto current = std::prev(packed_path_end); current > packed_path_begin;
Expand All @@ -442,7 +443,7 @@ EdgeDistance calculateEBGNodeDistance(const DataFacade<Algorithm> &facade,
if (unpacking_cache.IsEdgeInCache(std::make_tuple(
std::get<0>(edge), std::get<1>(edge), facade.GetExcludeIndex())))
{
EdgeDuration distance = unpacking_cache.GetDistance(std::make_tuple(
EdgeDuration distance = unpacking_cache.GetAnnotation(std::make_tuple(
std::get<0>(edge), std::get<1>(edge), facade.GetExcludeIndex()));
distance_stack.emplace(distance);
}
Expand Down
10 changes: 7 additions & 3 deletions include/engine/search_engine_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>

using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
using UnpackingCachePtr = boost::thread_specific_ptr<UnpackingCache>;
using DistanceCachePtr = boost::thread_specific_ptr<UnpackingCache<EdgeDistance>>;
using DurationCachePtr = boost::thread_specific_ptr<UnpackingCache<EdgeDuration>>;

static SearchEngineHeapPtr forward_heap_1;
static SearchEngineHeapPtr reverse_heap_1;
Expand All @@ -56,7 +57,8 @@ template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
static SearchEngineHeapPtr forward_heap_3;
static SearchEngineHeapPtr reverse_heap_3;
static ManyToManyHeapPtr many_to_many_heap;
static UnpackingCachePtr unpacking_cache;
static DistanceCachePtr distance_cache;
static DurationCachePtr duration_cache;

void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);

Expand All @@ -66,7 +68,9 @@ template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>

void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);

void InitializeOrClearUnpackingCacheThreadLocalStorage(unsigned timestamp);
void InitializeOrClearDistanceCacheThreadLocalStorage(unsigned timestamp);

void InitializeOrClearDurationCacheThreadLocalStorage(unsigned timestamp);
};

struct MultiLayerDijkstraHeapData
Expand Down
66 changes: 8 additions & 58 deletions include/engine/unpacking_cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include "../../third_party/compute_detail/lru_cache.hpp"
#include "util/typedefs.hpp"


// sizeof size_t: 8
// sizeof unsigned: 4
// sizeof unchar: 1
Expand All @@ -20,63 +19,14 @@ typedef unsigned char ExcludeIndex;
typedef unsigned Timestamp;
typedef std::tuple<NodeID, NodeID, unsigned char> Key;

class UnpackingCache
template <typename AnnotationType> class UnpackingCache
{
private:
boost::compute::detail::lru_cache<std::tuple<NodeID, NodeID, unsigned char>, EdgeDuration> m_cache;
boost::compute::detail::lru_cache<std::tuple<NodeID, NodeID, unsigned char>, AnnotationType>
m_cache;
unsigned m_current_data_timestamp = 0;

public:
// TO FIGURE OUT HOW MANY LINES TO INITIALIZE CACHE TO:
// Assume max cache size is 500mb (see bottom of OP here:
// https://github.com/Project-OSRM/osrm-backend/issues/4798#issue-288608332)

// LRU CACHE IMPLEMENTATION HAS THESE TWO STORAGE CONTAINERS
// Key is of size: std::uint32_t * 2 + (unsigned char) * 1
// = 4 * 2 + 1 * 1 = 9
// map: n * Key + n * EdgeDuration
// = n * 9 bytes + n * std::int32_t
// = n * 9 bytes + n * 4 bytes
// = n * 13 bytes
// list: n * Key
// = n * 9 bytes
// Total = n * (13 + 9) = n * 22 bytes
// Total cache size: 500 mb = 500 * 1024 *1024 bytes = 524288000 bytes

// THREAD LOCAL STORAGE (500 mb)
// Number of lines we need = 524288000 / 22 / number of threads = 23831272 / number of threads
// 16 threads: 23831272 / 16 = 1489454
// 8 threads: 23831272 / 8 = 2978909
// 4 threads: 23831272 / 4 = 5957818
// 2 threads: 23831272 / 2 = 11915636

// THREAD LOCAL STORAGE (1024 mb)
// Number of lines we need = 1073741824 / 22 / number of threads = 48806446 / number of threads
// 16 threads: 48806446 / 16 = 3050402
// 8 threads: 48806446 / 8 = 6100805
// 4 threads: 48806446 / 4 = 12201611
// 2 threads: 48806446 / 2 = 24403223

// LRU CACHE IMPLEMENTATION HAS THESE TWO STORAGE CONTAINERS
// Key is of size: std::uint32_t * 2 + (unsigned char) * 1 + unsigned * 1
// = 4 * 2 + 1 * 1 + 4 * 1 = 13
// map: n * Key + n * EdgeDuration
// = n * 13 bytes + n * std::int32_t
// = n * 13 bytes + n * 4 bytes
// = n * 17 bytes
// list: n * Key
// = n * 13 bytes
// Total = n * (17 + 13) = n * 30 bytes
// Total cache size: 500 mb = 500 * 1024 *1024 bytes = 524288000 bytes
// Total cache size: 1024 mb = 1024 * 1024 *1024 bytes = 1073741824 bytes
// Total cache size: 250 mb = 250 * 1024 *1024 bytes = 262144000 bytes

// SHARED STORAGE CACHE
// Number of lines for shared storage cache 1024 mb = 524288000 / 30 = 17476266
// Number of lines for shared storage cache 500 mb = 1073741824 / 30 = 35791394
// Number of lines for shared storage cache 250 mb = 262144000 / 30 = 8738133


UnpackingCache(unsigned timestamp) : m_cache(8738133), m_current_data_timestamp(timestamp){};

UnpackingCache(std::size_t cache_size, unsigned timestamp)
Expand All @@ -96,15 +46,15 @@ class UnpackingCache
return m_cache.contains(edge);
}

void AddEdge(std::tuple<NodeID, NodeID, unsigned char> edge, EdgeDuration duration)
void AddEdge(std::tuple<NodeID, NodeID, unsigned char> edge, AnnotationType annotation)
{
m_cache.insert(edge, duration);
m_cache.insert(edge, annotation);
}

EdgeDuration GetDuration(std::tuple<NodeID, NodeID, unsigned char> edge)
AnnotationType GetAnnotation(std::tuple<NodeID, NodeID, unsigned char> edge)
{
boost::optional<EdgeDuration> duration = m_cache.get(edge);
return duration ? *duration : MAXIMAL_EDGE_DURATION;
boost::optional<AnnotationType> annotation = m_cache.get(edge);
return annotation ? *annotation : MAXIMAL_EDGE_DURATION;
}
};
} // engine
Expand Down
18 changes: 11 additions & 7 deletions src/engine/routing_algorithms/many_to_many_ch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ void calculateDistances(typename SearchEngineData<ch::Algorithm>::ManyToManyQuer
const std::size_t number_of_targets,
const std::vector<NodeBucket> &search_space_with_buckets,
std::vector<EdgeDistance> &distances_table,
const std::vector<NodeID> &middle_nodes_table)
const std::vector<NodeID> &middle_nodes_table,
const SearchEngineData<ch::Algorithm> &engine_working_data)
{
std::vector<NodeID> packed_leg;

Expand Down Expand Up @@ -240,8 +241,10 @@ void calculateDistances(typename SearchEngineData<ch::Algorithm>::ManyToManyQuer
}
if (!packed_leg.empty())
{
auto annotation =
ch::calculateEBGNodeAnnotations(facade, packed_leg.begin(), packed_leg.end());
auto annotation = ch::calculateEBGNodeDistance(facade,
packed_leg.begin(),
packed_leg.end(),
*(engine_working_data.distance_cache));

distances_table[row_index * number_of_targets + column_index] = annotation;

Expand Down Expand Up @@ -337,9 +340,6 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
std::vector<NodeBucket> search_space_with_buckets;
std::vector<NodeID> packed_leg;

engine_working_data.InitializeOrClearUnpackingCacheThreadLocalStorage(
facade.GetTimestamp()); // always pass in the timestamp and clear if it's different

// Populate buckets with paths from all accessible nodes to destinations via backward searches
for (std::uint32_t column_index = 0; column_index < target_indices.size(); ++column_index)
{
Expand Down Expand Up @@ -390,6 +390,9 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,

if (calculate_distance)
{
engine_working_data.InitializeOrClearDistanceCacheThreadLocalStorage(
facade.GetTimestamp()); // always pass in the timestamp and clear if it's different

distances_table.resize(number_of_entries, INVALID_EDGE_DISTANCE);
calculateDistances(query_heap,
facade,
Expand All @@ -401,7 +404,8 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
number_of_targets,
search_space_with_buckets,
distances_table,
middle_nodes_table);
middle_nodes_table,
engine_working_data);
}
}

Expand Down
Loading

0 comments on commit 144c4d6

Please sign in to comment.