shared storage with mutex
shared lock for reads and unique lock for writes declare cache as object and not pointer in serach engine data to simulate singleton declaration put a lock infront of the clear function to make it threadsafe remove clear function from cache because cache will never get dropped unit tests unit tests and timestamp as part of key cache generations hash the key 500 mb 1000 mb 250 mb rebase against implement-cache
This commit is contained in:
parent
4563d44180
commit
c5acd6e6f7
@ -323,11 +323,16 @@ EdgeDuration calculateEBGNodeAnnotations(const DataFacade<Algorithm> &facade,
|
||||
|
||||
std::get<2>(edge) = true; // mark that this edge will now be processed
|
||||
|
||||
if (unpacking_cache.IsEdgeInCache(std::make_tuple(
|
||||
std::get<0>(edge), std::get<1>(edge), facade.GetExcludeIndex())))
|
||||
if (unpacking_cache.IsEdgeInCache(std::make_tuple(std::get<0>(edge),
|
||||
std::get<1>(edge),
|
||||
facade.GetExcludeIndex(),
|
||||
facade.GetTimestamp())))
|
||||
{
|
||||
EdgeDuration duration = unpacking_cache.GetDuration(std::make_tuple(
|
||||
std::get<0>(edge), std::get<1>(edge), facade.GetExcludeIndex()));
|
||||
EdgeDuration duration =
|
||||
unpacking_cache.GetDuration(std::make_tuple(std::get<0>(edge),
|
||||
std::get<1>(edge),
|
||||
facade.GetExcludeIndex(),
|
||||
facade.GetTimestamp()));
|
||||
duration_stack.emplace(duration);
|
||||
}
|
||||
else
|
||||
@ -369,8 +374,10 @@ EdgeDuration calculateEBGNodeAnnotations(const DataFacade<Algorithm> &facade,
|
||||
}
|
||||
else
|
||||
{
|
||||
auto temp = std::make_tuple(
|
||||
std::get<0>(edge), std::get<1>(edge), facade.GetExcludeIndex());
|
||||
auto temp = std::make_tuple(std::get<0>(edge),
|
||||
std::get<1>(edge),
|
||||
facade.GetExcludeIndex(),
|
||||
facade.GetTimestamp());
|
||||
// compute the duration here and put it onto the duration stack using method
|
||||
// similar to annotatePath but smaller
|
||||
EdgeDuration duration =
|
||||
@ -391,8 +398,10 @@ EdgeDuration calculateEBGNodeAnnotations(const DataFacade<Algorithm> &facade,
|
||||
duration_stack.pop();
|
||||
EdgeDuration duration = edge1 + edge2;
|
||||
duration_stack.emplace(duration);
|
||||
unpacking_cache.AddEdge(
|
||||
std::make_tuple(std::get<0>(edge), std::get<1>(edge), facade.GetExcludeIndex()),
|
||||
unpacking_cache.AddEdge(std::make_tuple(std::get<0>(edge),
|
||||
std::get<1>(edge),
|
||||
facade.GetExcludeIndex(),
|
||||
facade.GetTimestamp()),
|
||||
duration);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
#include "util/query_heap.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
// #include <boost/thread/tss.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@ -47,7 +48,6 @@ 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>;
|
||||
|
||||
static SearchEngineHeapPtr forward_heap_1;
|
||||
static SearchEngineHeapPtr reverse_heap_1;
|
||||
@ -56,7 +56,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 UnpackingCache unpacking_cache;
|
||||
|
||||
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
||||
|
||||
@ -65,8 +66,6 @@ template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
|
||||
void InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearUnpackingCacheThreadLocalStorage(unsigned timestamp);
|
||||
};
|
||||
|
||||
struct MultiLayerDijkstraHeapData
|
||||
|
||||
@ -2,10 +2,7 @@
|
||||
#define UNPACKING_CACHE_HPP
|
||||
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
<<<<<<< HEAD
|
||||
#include <boost/thread.hpp>
|
||||
=======
|
||||
>>>>>>> 68659b398... set up for computing durations while unpacking them
|
||||
|
||||
#include "../../third_party/compute_detail/lru_cache.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
@ -20,13 +17,13 @@ namespace engine
|
||||
{
|
||||
typedef unsigned char ExcludeIndex;
|
||||
typedef unsigned Timestamp;
|
||||
typedef std::tuple<NodeID, NodeID, unsigned char> Key;
|
||||
typedef std::tuple<NodeID, NodeID, ExcludeIndex, Timestamp> Key;
|
||||
|
||||
class UnpackingCache
|
||||
{
|
||||
private:
|
||||
boost::compute::detail::lru_cache<std::tuple<NodeID, NodeID, unsigned char>, EdgeDuration> m_cache;
|
||||
unsigned m_current_data_timestamp = 0;
|
||||
boost::compute::detail::lru_cache<Key, EdgeDuration> m_cache;
|
||||
boost::shared_mutex m_shared_access;
|
||||
|
||||
public:
|
||||
// TO FIGURE OUT HOW MANY LINES TO INITIALIZE CACHE TO:
|
||||
@ -34,62 +31,69 @@ class UnpackingCache
|
||||
// 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 + unsigned * 1
|
||||
// = 4 * 2 + 1 * 1 + 4 * 1 = 21
|
||||
// Key is of size: std::uint32_t * 2 + (unsigned char) * 1
|
||||
// = 4 * 2 + 1 * 1 = 9
|
||||
// map: n * Key + n * EdgeDuration
|
||||
// = n * 21 bytes + n * std::int32_t
|
||||
// = n * 21 bytes + n * 4 bytes
|
||||
// = n * 25 bytes
|
||||
// = n * 9 bytes + n * std::int32_t
|
||||
// = n * 9 bytes + n * 4 bytes
|
||||
// = n * 13 bytes
|
||||
// list: n * Key
|
||||
// = n * 21 bytes
|
||||
// Total = n * (25 + 21) = n * 46 bytes
|
||||
// = n * 9 bytes
|
||||
// Total = n * (13 + 9) = n * 22 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: 500 mb = 500 * 1024 *1024 bytes = 524288000 bytes
|
||||
|
||||
// THREAD LOCAL STORAGE (500 mb)
|
||||
// Number of lines we need = 524288000 / 46 / number of threads = 11397565 / number of threads
|
||||
// 16 threads: 11397565 / 16 = 712347
|
||||
// 8 threads: 11397565 / 8 = 1424695
|
||||
// 4 threads: 11397565 / 4 = 2849391
|
||||
// 2 threads: 11397565 / 2 = 5698782
|
||||
// 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 / 46 / number of threads = 23342213 / number of threads
|
||||
// 16 threads: 23342213 / 16 = 1458888
|
||||
// 8 threads: 23342213 / 8 = 2917776
|
||||
// 4 threads: 23342213 / 4 = 5835553
|
||||
// 2 threads: 23342213 / 2 = 11671106
|
||||
// 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: 500 mb = 500 * 1024 *1024 bytes = 524288000 bytes
|
||||
|
||||
// SHARED STORAGE CACHE
|
||||
// Number of lines we need for shared storage cache = 524288000 / 20 = 26214400
|
||||
// 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 = 11397565 / 30 = 379918
|
||||
|
||||
UnpackingCache(unsigned timestamp) : m_cache(11671106), m_current_data_timestamp(timestamp){};
|
||||
UnpackingCache() : m_cache(17476266){};
|
||||
|
||||
UnpackingCache(std::size_t cache_size, unsigned timestamp)
|
||||
: m_cache(cache_size), m_current_data_timestamp(timestamp){};
|
||||
|
||||
void Clear(unsigned new_data_timestamp)
|
||||
{
|
||||
if (m_current_data_timestamp != new_data_timestamp)
|
||||
{
|
||||
m_cache.clear();
|
||||
m_current_data_timestamp = new_data_timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsEdgeInCache(std::tuple<NodeID, NodeID, unsigned char> edge)
|
||||
bool IsEdgeInCache(Key edge)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock(m_shared_access);
|
||||
return m_cache.contains(edge);
|
||||
}
|
||||
|
||||
void AddEdge(std::tuple<NodeID, NodeID, unsigned char> edge, EdgeDuration duration)
|
||||
void AddEdge(Key edge, EdgeDuration duration)
|
||||
{
|
||||
boost::unique_lock<boost::shared_mutex> lock(m_shared_access);
|
||||
m_cache.insert(edge, duration);
|
||||
}
|
||||
|
||||
EdgeDuration GetDuration(std::tuple<NodeID, NodeID, unsigned char> edge)
|
||||
EdgeDuration GetDuration(Key edge)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock(m_shared_access);
|
||||
boost::optional<EdgeDuration> duration = m_cache.get(edge);
|
||||
return duration ? *duration : MAXIMAL_EDGE_DURATION;
|
||||
}
|
||||
|
||||
@ -225,9 +225,6 @@ std::vector<EdgeDuration> manyToManySearch(SearchEngineData<ch::Algorithm> &engi
|
||||
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_idx = 0; column_idx < target_indices.size(); ++column_idx)
|
||||
{
|
||||
@ -321,7 +318,7 @@ std::vector<EdgeDuration> manyToManySearch(SearchEngineData<ch::Algorithm> &engi
|
||||
ch::calculateEBGNodeAnnotations(facade,
|
||||
packed_leg.begin(),
|
||||
packed_leg.end(),
|
||||
*engine_working_data.unpacking_cache.get());
|
||||
engine_working_data.unpacking_cache);
|
||||
|
||||
// check the direction of travel to figure out how to calculate the offset to/from
|
||||
// the source/target
|
||||
|
||||
@ -14,7 +14,7 @@ SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::reverse_heap_2;
|
||||
SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::forward_heap_3;
|
||||
SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::reverse_heap_3;
|
||||
SearchEngineData<CH>::ManyToManyHeapPtr SearchEngineData<CH>::many_to_many_heap;
|
||||
SearchEngineData<CH>::UnpackingCachePtr SearchEngineData<CH>::unpacking_cache;
|
||||
UnpackingCache SearchEngineData<CH>::unpacking_cache;
|
||||
|
||||
void SearchEngineData<CH>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
||||
{
|
||||
@ -91,18 +91,6 @@ void SearchEngineData<CH>::InitializeOrClearManyToManyThreadLocalStorage(unsigne
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEngineData<CH>::InitializeOrClearUnpackingCacheThreadLocalStorage(unsigned timestamp)
|
||||
{
|
||||
if (unpacking_cache.get())
|
||||
{
|
||||
unpacking_cache->Clear(timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
unpacking_cache.reset(new UnpackingCache(timestamp));
|
||||
}
|
||||
}
|
||||
|
||||
// MLD
|
||||
using MLD = routing_algorithms::mld::Algorithm;
|
||||
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::forward_heap_1;
|
||||
|
||||
@ -16,9 +16,9 @@ BOOST_AUTO_TEST_CASE(add_edge_and_check_existence)
|
||||
{
|
||||
// Arrange (Setup)
|
||||
unsigned timestamp = 1522782542;
|
||||
UnpackingCache cache(1, timestamp);
|
||||
UnpackingCache cache(1);
|
||||
|
||||
auto key = std::make_tuple(1, 1, 1);
|
||||
auto key = std::make_tuple(1, 1, 1, timestamp);
|
||||
auto value = 1;
|
||||
|
||||
// Act
|
||||
@ -26,7 +26,7 @@ BOOST_AUTO_TEST_CASE(add_edge_and_check_existence)
|
||||
|
||||
// Assert
|
||||
BOOST_CHECK(cache.IsEdgeInCache(key) == true);
|
||||
BOOST_CHECK(cache.IsEdgeInCache(std::make_tuple(2, 2, 2)) == false);
|
||||
BOOST_CHECK(cache.IsEdgeInCache(std::make_tuple(2, 2, 2, timestamp)) == false);
|
||||
|
||||
auto result = cache.GetDuration(key);
|
||||
BOOST_CHECK_EQUAL(result, value);
|
||||
@ -35,13 +35,12 @@ BOOST_AUTO_TEST_CASE(add_edge_and_check_existence)
|
||||
BOOST_AUTO_TEST_CASE(cache_invalidation)
|
||||
{
|
||||
// Arrange (Setup)
|
||||
unsigned timestamp = 1522782542;
|
||||
UnpackingCache cache(1, timestamp);
|
||||
UnpackingCache cache(1);
|
||||
|
||||
auto key1 = std::make_tuple(1, 1, 1);
|
||||
auto key1 = std::make_tuple(1, 1, 1, 1522782542);
|
||||
auto value1 = 1;
|
||||
|
||||
auto key2 = std::make_tuple(2, 2, 2);
|
||||
auto key2 = std::make_tuple(2, 2, 2, 1522782543);
|
||||
auto value2 = 2;
|
||||
|
||||
// Act
|
||||
@ -56,31 +55,34 @@ BOOST_AUTO_TEST_CASE(cache_invalidation)
|
||||
BOOST_CHECK_EQUAL(result, value2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(new_data)
|
||||
BOOST_AUTO_TEST_CASE(store_generations)
|
||||
{
|
||||
// Arrange (Setup)
|
||||
UnpackingCache cache(2);
|
||||
|
||||
unsigned timestamp1 = 1522782542;
|
||||
unsigned timestamp2 = 1522782543;
|
||||
|
||||
UnpackingCache cache(1, timestamp1);
|
||||
|
||||
auto key1 = std::make_tuple(1, 2, 3);
|
||||
auto key1 = std::make_tuple(1, 1, 1, timestamp1);
|
||||
auto value1 = 1;
|
||||
auto key2 = std::make_tuple(2, 3, 4);
|
||||
|
||||
auto key2 = std::make_tuple(1, 1, 1, timestamp2);
|
||||
auto value2 = 2;
|
||||
|
||||
// Act
|
||||
cache.AddEdge(key1, value1);
|
||||
cache.Clear(timestamp2);
|
||||
cache.AddEdge(key2, value2);
|
||||
|
||||
// Assert
|
||||
BOOST_CHECK(cache.IsEdgeInCache(key1) == false);
|
||||
BOOST_CHECK(cache.IsEdgeInCache(key1) == true);
|
||||
BOOST_CHECK(cache.IsEdgeInCache(key2) == true);
|
||||
BOOST_CHECK(cache.IsEdgeInCache(std::make_tuple(2, 2, 2)) == false);
|
||||
BOOST_CHECK(cache.IsEdgeInCache(std::make_tuple(2, 2, 2, timestamp1)) == false);
|
||||
|
||||
auto result = cache.GetDuration(key2);
|
||||
BOOST_CHECK_EQUAL(result, value2);
|
||||
auto result1 = cache.GetDuration(key1);
|
||||
BOOST_CHECK_EQUAL(result1, value1);
|
||||
|
||||
auto result2 = cache.GetDuration(key2);
|
||||
BOOST_CHECK_EQUAL(result2, value2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user