Skip to content

Commit

Permalink
use unpacking on distance and templatize the cache
Browse files Browse the repository at this point in the history
comment about cache size

update unit tests
  • Loading branch information
ghoshkaj committed May 6, 2018
1 parent fbba23e commit 62d7d08
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 179 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
73 changes: 10 additions & 63 deletions include/engine/unpacking_cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@
#include "../../third_party/compute_detail/lru_cache.hpp"
#include "util/typedefs.hpp"


// sizeof size_t: 8
// sizeof unsigned: 4
// sizeof unchar: 1
// sizeof uint32: 4
namespace osrm
{
namespace engine
Expand All @@ -20,63 +15,15 @@ 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, ExcludeIndex>, AnnotationType>
m_cache;
unsigned m_current_data_timestamp = 0;
const AnnotationType INVALID_EDGE_ANNOTATION = std::numeric_limits<AnnotationType>::max();

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 @@ -91,20 +38,20 @@ class UnpackingCache
}
}

bool IsEdgeInCache(std::tuple<NodeID, NodeID, unsigned char> edge)
bool IsEdgeInCache(std::tuple<NodeID, NodeID, ExcludeIndex> edge)
{
return m_cache.contains(edge);
}

void AddEdge(std::tuple<NodeID, NodeID, unsigned char> edge, EdgeDuration duration)
void AddEdge(std::tuple<NodeID, NodeID, ExcludeIndex> 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, ExcludeIndex> 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 : INVALID_EDGE_ANNOTATION;
}
};
} // 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 62d7d08

Please sign in to comment.