Pull everthing in the facades
This commit is contained in:
parent
ff0a98196f
commit
108fce896b
@ -23,10 +23,10 @@ struct MLD final
|
||||
{
|
||||
};
|
||||
|
||||
template<typename AlgorithmT> const char* name();
|
||||
template<> inline const char* name<CH>() { return "CH"; }
|
||||
template<> inline const char* name<CoreCH>() { return "CoreCH"; }
|
||||
template<> inline const char* name<MLD>() { return "MLD"; }
|
||||
template <typename AlgorithmT> const char *name();
|
||||
template <> inline const char *name<CH>() { return "CH"; }
|
||||
template <> inline const char *name<CoreCH>() { return "CoreCH"; }
|
||||
template <> inline const char *name<MLD>() { return "MLD"; }
|
||||
}
|
||||
|
||||
namespace algorithm_trais
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
#include "contractor/query_edge.hpp"
|
||||
#include "engine/algorithm.hpp"
|
||||
#include "util/cell_storage.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/multi_level_partition.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@ -58,6 +60,14 @@ template <> class AlgorithmDataFacade<algorithm::CoreCH>
|
||||
|
||||
virtual bool IsCoreNode(const NodeID id) const = 0;
|
||||
};
|
||||
|
||||
template <> class AlgorithmDataFacade<algorithm::MLD>
|
||||
{
|
||||
public:
|
||||
virtual const util::MultiLevelPartitionView &GetMultiLevelPartition() const = 0;
|
||||
|
||||
virtual const util::CellStorage<true> &GetCellStorage() const = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -251,10 +251,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
std::shared_ptr<util::RangeTable<16, true>> m_bearing_ranges_table;
|
||||
util::ShM<DiscreteBearing, true>::vector m_bearing_values_table;
|
||||
|
||||
// MLD data
|
||||
util::PackedMultiLevelPartition<true> mld_partition;
|
||||
util::CellStorage<true> mld_cell_storage;
|
||||
|
||||
// allocator that keeps the allocation data
|
||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||
|
||||
@ -540,27 +536,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
m_entry_class_table = std::move(entry_class_table);
|
||||
}
|
||||
|
||||
void InitializeMLDDataPointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
{
|
||||
if (data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_PARTITION) > 0)
|
||||
{
|
||||
auto mld_partition_ptr =
|
||||
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::MLD_CELL_PARTITION);
|
||||
mld_partition.InitializePointers(
|
||||
mld_partition_ptr,
|
||||
mld_partition_ptr + data_layout.num_entries[storage::DataLayout::MLD_CELL_PARTITION]);
|
||||
}
|
||||
|
||||
if (data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_STORAGE) > 0)
|
||||
{
|
||||
auto mld_cell_storage_ptr =
|
||||
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::MLD_CELL_STORAGE);
|
||||
mld_cell_storage.InitializePointers(
|
||||
mld_cell_storage_ptr,
|
||||
mld_cell_storage_ptr + data_layout.num_entries[storage::DataLayout::MLD_CELL_STORAGE]);
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
{
|
||||
InitializeChecksumPointer(data_layout, memory_block);
|
||||
@ -574,7 +549,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
InitializeProfilePropertiesPointer(data_layout, memory_block);
|
||||
InitializeRTreePointers(data_layout, memory_block);
|
||||
InitializeIntersectionClassPointers(data_layout, memory_block);
|
||||
InitializeMLDDataPointers(data_layout, memory_block);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1077,13 +1051,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
m_lane_description_masks.begin() +
|
||||
m_lane_description_offsets[lane_description_id + 1]);
|
||||
}
|
||||
|
||||
const util::PackedMultiLevelPartition<true> &GetMultiLevelPartition() const
|
||||
{
|
||||
return mld_partition;
|
||||
}
|
||||
|
||||
const util::CellStorage<true> &GetCellStorage() const { return mld_cell_storage; }
|
||||
};
|
||||
|
||||
template <typename AlgorithmT> class ContiguousInternalMemoryDataFacade;
|
||||
@ -1115,6 +1082,83 @@ class ContiguousInternalMemoryDataFacade<algorithm::CoreCH> final
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
: public datafacade::AlgorithmDataFacade<algorithm::MLD>
|
||||
{
|
||||
// MLD data
|
||||
util::MultiLevelPartitionView mld_partition;
|
||||
util::CellStorage<true> mld_cell_storage;
|
||||
|
||||
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
{
|
||||
InitializeMLDDataPointers(data_layout, memory_block);
|
||||
}
|
||||
|
||||
void InitializeMLDDataPointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
{
|
||||
if (data_layout.GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0)
|
||||
{
|
||||
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_LEVEL_DATA) > 0);
|
||||
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0);
|
||||
|
||||
auto level_data = *data_layout.GetBlockPtr<util::MultiLevelPartitionView::LevelData>(memory_block, storage::DataLayout::MLD_PARTITION);
|
||||
|
||||
auto mld_partition_ptr = data_layout.GetBlockPtr<util::PartitionID>(memory_block, storage::DataLayout::MLD_PARTITION);
|
||||
auto partition_entries_count = data_layout.GetBlockEntries(storage::DataLayout::MLD_PARTITION);
|
||||
util::ShM<util::PartitionID, true>::vector partition(mld_partition_ptr, partition_entries_count);
|
||||
|
||||
auto mld_chilren_ptr = data_layout.GetBlockPtr<util::CellID>(memory_block, storage::DataLayout::MLD_CELL_TO_CHILDREN);
|
||||
auto children_entries_count = data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_TO_CHILDREN);
|
||||
util::ShM<util::CellID, true>::vector cell_to_children(mld_chilren_ptr, children_entries_count);
|
||||
|
||||
mld_partition = util::MultiLevelPartitionView{level_data, partition, cell_to_children};
|
||||
}
|
||||
|
||||
if (data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_STORAGE) > 0)
|
||||
{
|
||||
auto mld_cell_storage_ptr =
|
||||
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::MLD_CELL_STORAGE);
|
||||
mld_cell_storage.InitializePointers(
|
||||
mld_cell_storage_ptr,
|
||||
mld_cell_storage_ptr +
|
||||
data_layout.num_entries[storage::DataLayout::MLD_CELL_STORAGE]);
|
||||
}
|
||||
}
|
||||
|
||||
// allocator that keeps the allocation data
|
||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||
|
||||
public:
|
||||
ContiguousInternalMemoryAlgorithmDataFacade(
|
||||
std::shared_ptr<ContiguousBlockAllocator> allocator_)
|
||||
: allocator(std::move(allocator_))
|
||||
{
|
||||
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
|
||||
}
|
||||
|
||||
const util::MultiLevelPartitionView &GetMultiLevelPartition() const
|
||||
{
|
||||
return mld_partition;
|
||||
}
|
||||
|
||||
const util::CellStorage<true> &GetCellStorage() const { return mld_cell_storage; }
|
||||
};
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryDataFacade<algorithm::MLD>
|
||||
: public ContiguousInternalMemoryDataFacadeBase,
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
{
|
||||
public:
|
||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
|
||||
: ContiguousInternalMemoryDataFacadeBase(allocator),
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>(allocator)
|
||||
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,9 @@ namespace engine
|
||||
* now.
|
||||
* - Algorithm::CoreCH
|
||||
* Contractoin Hierachies with partial contraction for faster pre-processing but slower queries.
|
||||
* - Algorithm::MLD
|
||||
* Multi Level Dijkstra which is experimental and moderately fast in both pre-processing and
|
||||
* query.
|
||||
*
|
||||
* Algorithm::CH is specified we will automatically upgrade to CoreCH if we find the data for it.
|
||||
* If Algorithm::CoreCH is specified and we don't find the speedup data, we fail hard.
|
||||
@ -74,7 +77,8 @@ struct EngineConfig final
|
||||
enum class Algorithm
|
||||
{
|
||||
CH, // will upgrade to CoreCH if it finds core data
|
||||
CoreCH // will fail hard if there is no core data
|
||||
CoreCH, // will fail hard if there is no core data
|
||||
MLD
|
||||
};
|
||||
|
||||
storage::StorageConfig storage_config;
|
||||
|
@ -65,54 +65,29 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
|
||||
virtual ~RoutingAlgorithms() = default;
|
||||
|
||||
InternalRouteResult
|
||||
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const final override
|
||||
{
|
||||
return routing_algorithms::alternativePathSearch(heaps, facade, phantom_node_pair);
|
||||
}
|
||||
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const final override;
|
||||
|
||||
InternalRouteResult ShortestPathSearch(
|
||||
const std::vector<PhantomNodes> &phantom_node_pair,
|
||||
const boost::optional<bool> continue_straight_at_waypoint) const final override
|
||||
{
|
||||
return routing_algorithms::shortestPathSearch(
|
||||
heaps, facade, phantom_node_pair, continue_straight_at_waypoint);
|
||||
}
|
||||
const boost::optional<bool> continue_straight_at_waypoint) const final override;
|
||||
|
||||
InternalRouteResult
|
||||
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override
|
||||
{
|
||||
return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_nodes);
|
||||
}
|
||||
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
|
||||
|
||||
std::vector<EdgeWeight>
|
||||
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices) const final override
|
||||
{
|
||||
return routing_algorithms::manyToManySearch(
|
||||
heaps, facade, phantom_nodes, source_indices, target_indices);
|
||||
}
|
||||
const std::vector<std::size_t> &target_indices) const final override;
|
||||
|
||||
routing_algorithms::SubMatchingList MapMatching(
|
||||
const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision) const final override
|
||||
{
|
||||
return routing_algorithms::mapMatching(heaps,
|
||||
facade,
|
||||
candidates_list,
|
||||
trace_coordinates,
|
||||
trace_timestamps,
|
||||
trace_gps_precision);
|
||||
}
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision) const final override;
|
||||
|
||||
std::vector<routing_algorithms::TurnData>
|
||||
GetTileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
|
||||
const std::vector<std::size_t> &sorted_edge_indexes) const final override
|
||||
{
|
||||
return routing_algorithms::getTileTurns(facade, edges, sorted_edge_indexes);
|
||||
}
|
||||
const std::vector<std::size_t> &sorted_edge_indexes) const final override;
|
||||
|
||||
bool HasAlternativePathSearch() const final override
|
||||
{
|
||||
@ -149,6 +124,108 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
|
||||
// Owned by shared-ptr passed to the query
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade;
|
||||
};
|
||||
|
||||
template <typename AlgorithmT>
|
||||
InternalRouteResult
|
||||
RoutingAlgorithms<AlgorithmT>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
|
||||
{
|
||||
return routing_algorithms::alternativePathSearch(heaps, facade, phantom_node_pair);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
InternalRouteResult RoutingAlgorithms<AlgorithmT>::ShortestPathSearch(
|
||||
const std::vector<PhantomNodes> &phantom_node_pair,
|
||||
const boost::optional<bool> continue_straight_at_waypoint) const
|
||||
{
|
||||
return routing_algorithms::shortestPathSearch(
|
||||
heaps, facade, phantom_node_pair, continue_straight_at_waypoint);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
InternalRouteResult
|
||||
RoutingAlgorithms<AlgorithmT>::DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const
|
||||
{
|
||||
return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_nodes);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
std::vector<EdgeWeight> RoutingAlgorithms<AlgorithmT>::ManyToManySearch(
|
||||
const std::vector<PhantomNode> &phantom_nodes,
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices) const
|
||||
{
|
||||
return routing_algorithms::manyToManySearch(
|
||||
heaps, facade, phantom_nodes, source_indices, target_indices);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMatching(
|
||||
const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision) const
|
||||
{
|
||||
return routing_algorithms::mapMatching(
|
||||
heaps, facade, candidates_list, trace_coordinates, trace_timestamps, trace_gps_precision);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<AlgorithmT>::GetTileTurns(
|
||||
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
|
||||
const std::vector<std::size_t> &sorted_edge_indexes) const
|
||||
{
|
||||
return routing_algorithms::getTileTurns(facade, edges, sorted_edge_indexes);
|
||||
}
|
||||
|
||||
// MLD overrides for not implemented
|
||||
template <>
|
||||
InternalRouteResult inline RoutingAlgorithms<algorithm::MLD>::AlternativePathSearch(
|
||||
const PhantomNodes &) const
|
||||
{
|
||||
throw util::exception("AlternativePathSearch is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline InternalRouteResult
|
||||
RoutingAlgorithms<algorithm::MLD>::ShortestPathSearch(const std::vector<PhantomNodes> &,
|
||||
const boost::optional<bool>) const
|
||||
{
|
||||
throw util::exception("ShortestPathSearch is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
InternalRouteResult inline RoutingAlgorithms<algorithm::MLD>::DirectShortestPathSearch(
|
||||
const PhantomNodes &) const
|
||||
{
|
||||
throw util::exception("DirectShortestPathSearch is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::vector<EdgeWeight>
|
||||
RoutingAlgorithms<algorithm::MLD>::ManyToManySearch(const std::vector<PhantomNode> &,
|
||||
const std::vector<std::size_t> &,
|
||||
const std::vector<std::size_t> &) const
|
||||
{
|
||||
throw util::exception("ManyToManySearch is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline routing_algorithms::SubMatchingList
|
||||
RoutingAlgorithms<algorithm::MLD>::MapMatching(const routing_algorithms::CandidateLists &,
|
||||
const std::vector<util::Coordinate> &,
|
||||
const std::vector<unsigned> &,
|
||||
const std::vector<boost::optional<double>> &) const
|
||||
{
|
||||
throw util::exception("MapMatching is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<algorithm::MLD>::GetTileTurns(
|
||||
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &,
|
||||
const std::vector<std::size_t> &) const
|
||||
{
|
||||
throw util::exception("GetTileTurns is not implemented");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
28
include/partition/io.hpp
Normal file
28
include/partition/io.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef OSRM_PARTITION_IO_HPP
|
||||
#define OSRM_PARTITION_IO_HPP
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "util/multi_level_partition.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
template <>
|
||||
inline void write(const boost::filesystem::path &path, const util::MultiLevelPartition &mlp)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.WriteOne(mlp.level_data);
|
||||
writer.SerializeVector(mlp.partition);
|
||||
writer.SerializeVector(mlp.cell_to_children);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -13,10 +13,7 @@ namespace partition
|
||||
|
||||
struct PartitionConfig
|
||||
{
|
||||
PartitionConfig()
|
||||
: requested_num_threads(0)
|
||||
{
|
||||
}
|
||||
PartitionConfig() : requested_num_threads(0) {}
|
||||
|
||||
void UseDefaults()
|
||||
{
|
||||
@ -37,8 +34,8 @@ struct PartitionConfig
|
||||
compressed_node_based_graph_path = basepath + ".osrm.cnbg";
|
||||
cnbg_ebg_mapping_path = basepath + ".osrm.cnbg_to_ebg";
|
||||
partition_path = basepath + ".osrm.partition";
|
||||
mld_partition_path = basepath + ".osrm.mld_partition";
|
||||
mld_storage_path = basepath + ".osrm.mld_storage";
|
||||
mld_partition_path = basepath + ".osrm.partition";
|
||||
mld_storage_path = basepath + ".osrm.cells";
|
||||
}
|
||||
|
||||
// might be changed to the node based graph at some point
|
||||
|
@ -141,6 +141,13 @@ class FileReader
|
||||
return sizeof(count) + sizeof(T) * count;
|
||||
}
|
||||
|
||||
template <typename T> std::size_t ReadVectorSize()
|
||||
{
|
||||
const auto count = ReadElementCount64();
|
||||
Skip<T>(count);
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename T> void *DeserializeVector(void *begin, const void *end)
|
||||
{
|
||||
auto count = ReadElementCount64();
|
||||
|
@ -57,7 +57,9 @@ const constexpr char *block_id_to_name[] = {"NAME_CHAR_DATA",
|
||||
"LANE_DESCRIPTION_MASKS",
|
||||
"TURN_WEIGHT_PENALTIES",
|
||||
"TURN_DURATION_PENALTIES",
|
||||
"MLD_CELL_PARTITION",
|
||||
"MLD_LEVEL_DATA",
|
||||
"MLD_PARTITION",
|
||||
"MLD_CELL_TO_CHILDREN",
|
||||
"MLD_CELL_STORAGE"};
|
||||
|
||||
struct DataLayout
|
||||
@ -103,7 +105,9 @@ struct DataLayout
|
||||
LANE_DESCRIPTION_MASKS,
|
||||
TURN_WEIGHT_PENALTIES,
|
||||
TURN_DURATION_PENALTIES,
|
||||
MLD_CELL_PARTITION,
|
||||
MLD_LEVEL_DATA,
|
||||
MLD_PARTITION,
|
||||
MLD_CELL_TO_CHILDREN,
|
||||
MLD_CELL_STORAGE,
|
||||
NUM_BLOCKS
|
||||
};
|
||||
@ -122,6 +126,11 @@ struct DataLayout
|
||||
entry_align[bid] = alignof(T);
|
||||
}
|
||||
|
||||
inline uint64_t GetBlockEntries(BlockID bid) const
|
||||
{
|
||||
return num_entries[bid];
|
||||
}
|
||||
|
||||
inline uint64_t GetBlockSize(BlockID bid) const
|
||||
{
|
||||
// special bit encoding
|
||||
@ -169,6 +178,13 @@ struct DataLayout
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *GetBlockEnd(char *shared_memory, BlockID bid) const
|
||||
{
|
||||
auto begin = GetBlockPtr<T>(shared_memory, bid);
|
||||
return begin + GetBlockEntries(bid);
|
||||
}
|
||||
|
||||
template <typename T, bool WRITE_CANARY = false>
|
||||
inline T *GetBlockPtr(char *shared_memory, BlockID bid) const
|
||||
{
|
||||
|
@ -20,6 +20,27 @@
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
||||
namespace util
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class MultiLevelPartitionImpl;
|
||||
}
|
||||
using MultiLevelPartition = detail::MultiLevelPartitionImpl<false>;
|
||||
using MultiLevelPartitionView = detail::MultiLevelPartitionImpl<true>;
|
||||
}
|
||||
|
||||
namespace partition
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
template <bool UseShareMemory>
|
||||
void write(const boost::filesystem::path &file,
|
||||
const util::detail::MultiLevelPartitionImpl<UseShareMemory> &mlp);
|
||||
}
|
||||
}
|
||||
|
||||
namespace util
|
||||
{
|
||||
namespace detail
|
||||
@ -49,187 +70,121 @@ inline std::size_t highestMSB(std::uint64_t v)
|
||||
|
||||
using LevelID = std::uint8_t;
|
||||
using CellID = std::uint32_t;
|
||||
using PartitionID = std::uint64_t;
|
||||
|
||||
static constexpr CellID INVALID_CELL_ID = std::numeric_limits<CellID>::max();
|
||||
|
||||
// Mock interface, can be removed when we have an actual implementation
|
||||
class MultiLevelPartition
|
||||
namespace detail
|
||||
{
|
||||
public:
|
||||
// Returns the cell id of `node` at `level`
|
||||
virtual CellID GetCell(LevelID level, NodeID node) const = 0;
|
||||
|
||||
// Returns the lowest cell id (at `level - 1`) of all children `cell` at `level`
|
||||
virtual CellID BeginChildren(LevelID level, CellID cell) const = 0;
|
||||
|
||||
// Returns the highest cell id (at `level - 1`) of all children `cell` at `level`
|
||||
virtual CellID EndChildren(LevelID level, CellID cell) const = 0;
|
||||
|
||||
// Returns the highest level in which `first` and `second` are still in different cells
|
||||
virtual LevelID GetHighestDifferentLevel(NodeID first, NodeID second) const = 0;
|
||||
|
||||
// Returns the level at which a `node` is relevant for a query from start to target
|
||||
virtual LevelID GetQueryLevel(NodeID start, NodeID target, NodeID node) const = 0;
|
||||
|
||||
virtual std::uint8_t GetNumberOfLevels() const = 0;
|
||||
|
||||
virtual std::uint32_t GetNumberOfCells(LevelID level) const = 0;
|
||||
};
|
||||
|
||||
template <bool UseShareMemory> class PackedMultiLevelPartition final : public MultiLevelPartition
|
||||
template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
{
|
||||
using PartitionID = std::uint64_t;
|
||||
// we will support at most 16 levels
|
||||
static const constexpr std::uint8_t MAX_NUM_LEVEL = 16;
|
||||
static const constexpr std::uint8_t NUM_PARTITION_BITS = sizeof(PartitionID) * CHAR_BIT;
|
||||
|
||||
template <typename T> using Vector = typename util::ShM<T, UseShareMemory>::vector;
|
||||
|
||||
public:
|
||||
PackedMultiLevelPartition() {}
|
||||
// Contains all data necessary to describe the level hierarchy
|
||||
struct LevelData
|
||||
{
|
||||
|
||||
std::uint32_t num_level;
|
||||
std::array<std::uint8_t, MAX_NUM_LEVEL - 1> lidx_to_offset;
|
||||
std::array<PartitionID, MAX_NUM_LEVEL - 1> lidx_to_mask;
|
||||
std::array<LevelID, NUM_PARTITION_BITS> bit_to_level;
|
||||
std::array<std::uint32_t, MAX_NUM_LEVEL - 1> lidx_to_children_offsets;
|
||||
};
|
||||
|
||||
MultiLevelPartitionImpl() = default;
|
||||
|
||||
// cell_sizes is index by level (starting at 0, the base graph).
|
||||
// However level 0 always needs to have cell size 1, since it is the
|
||||
// basegraph.
|
||||
PackedMultiLevelPartition(const std::vector<std::vector<CellID>> &partitions,
|
||||
const std::vector<std::uint32_t> &level_to_num_cells)
|
||||
: level_offsets(makeLevelOffsets(level_to_num_cells)), level_masks(makeLevelMasks()),
|
||||
bit_to_level(makeBitToLevel())
|
||||
template <typename = typename std::enable_if<!UseShareMemory>>
|
||||
MultiLevelPartitionImpl(const std::vector<std::vector<CellID>> &partitions,
|
||||
const std::vector<std::uint32_t> &lidx_to_num_cells)
|
||||
: level_data(MakeLevelData(lidx_to_num_cells))
|
||||
{
|
||||
initializePartitionIDs(partitions);
|
||||
InitializePartitionIDs(partitions);
|
||||
}
|
||||
|
||||
PackedMultiLevelPartition(const boost::filesystem::path &file_name) { Read(file_name); }
|
||||
template <typename = typename std::enable_if<UseShareMemory>>
|
||||
MultiLevelPartitionImpl(LevelData level_data,
|
||||
Vector<PartitionID> partition_,
|
||||
Vector<CellID> cell_to_children_)
|
||||
: level_data(std::move(level_data)), partition(std::move(partition_)),
|
||||
cell_to_children(std::move(cell_to_children_))
|
||||
{
|
||||
}
|
||||
|
||||
// returns the index of the cell the vertex is contained at level l
|
||||
CellID GetCell(LevelID l, NodeID node) const final override
|
||||
CellID GetCell(LevelID l, NodeID node) const
|
||||
{
|
||||
auto p = partition[node];
|
||||
auto lidx = LevelIDToIndex(l);
|
||||
auto masked = p & level_masks[lidx];
|
||||
return masked >> level_offsets[lidx];
|
||||
auto masked = p & level_data.lidx_to_mask[lidx];
|
||||
return masked >> level_data.lidx_to_offset[lidx];
|
||||
}
|
||||
|
||||
LevelID GetQueryLevel(NodeID start, NodeID target, NodeID node) const final override
|
||||
LevelID GetQueryLevel(NodeID start, NodeID target, NodeID node) const
|
||||
{
|
||||
return std::min(GetHighestDifferentLevel(start, node),
|
||||
GetHighestDifferentLevel(target, node));
|
||||
}
|
||||
|
||||
LevelID GetHighestDifferentLevel(NodeID first, NodeID second) const final override
|
||||
LevelID GetHighestDifferentLevel(NodeID first, NodeID second) const
|
||||
{
|
||||
if (partition[first] == partition[second])
|
||||
return 0;
|
||||
|
||||
auto msb = detail::highestMSB(partition[first] ^ partition[second]);
|
||||
return bit_to_level[msb];
|
||||
return level_data.bit_to_level[msb];
|
||||
}
|
||||
|
||||
std::uint8_t GetNumberOfLevels() const final override { return level_offsets.size(); }
|
||||
std::uint8_t GetNumberOfLevels() const { return level_data.num_level; }
|
||||
|
||||
std::uint32_t GetNumberOfCells(LevelID level) const final override
|
||||
std::uint32_t GetNumberOfCells(LevelID level) const
|
||||
{
|
||||
return GetCell(level, GetSenitileNode());
|
||||
}
|
||||
|
||||
// Returns the lowest cell id (at `level - 1`) of all children `cell` at `level`
|
||||
CellID BeginChildren(LevelID level, CellID cell) const final override
|
||||
CellID BeginChildren(LevelID level, CellID cell) const
|
||||
{
|
||||
BOOST_ASSERT(level > 1);
|
||||
auto lidx = LevelIDToIndex(level);
|
||||
auto offset = level_to_children_offset[lidx];
|
||||
auto offset = level_data.lidx_to_children_offsets[lidx];
|
||||
return cell_to_children[offset + cell];
|
||||
}
|
||||
|
||||
// Returns the highest cell id (at `level - 1`) of all children `cell` at `level`
|
||||
CellID EndChildren(LevelID level, CellID cell) const final override
|
||||
CellID EndChildren(LevelID level, CellID cell) const
|
||||
{
|
||||
BOOST_ASSERT(level > 1);
|
||||
auto lidx = LevelIDToIndex(level);
|
||||
auto offset = level_to_children_offset[lidx];
|
||||
auto offset = level_data.lidx_to_children_offsets[lidx];
|
||||
return cell_to_children[offset + cell + 1];
|
||||
}
|
||||
|
||||
std::size_t GetRequiredMemorySize(const boost::filesystem::path &path) const
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
std::size_t memory_size = 0;
|
||||
memory_size += reader.GetVectorMemorySize<decltype(level_offsets[0])>();
|
||||
memory_size += reader.GetVectorMemorySize<decltype(partition[0])>();
|
||||
memory_size += reader.GetVectorMemorySize<decltype(level_to_children_offset[0])>();
|
||||
memory_size += reader.GetVectorMemorySize<decltype(cell_to_children[0])>();
|
||||
return memory_size;
|
||||
}
|
||||
|
||||
template <bool Q = UseShareMemory>
|
||||
typename std::enable_if<Q>::type
|
||||
Read(const boost::filesystem::path &path, void *begin, const void *end) const
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
begin = reader.DeserializeVector<typename decltype(level_offsets)::value_type>(begin, end);
|
||||
begin = reader.DeserializeVector<typename decltype(partition)::value_type>(begin, end);
|
||||
begin = reader.DeserializeVector<typename decltype(level_to_children_offset)::value_type>(
|
||||
begin, end);
|
||||
begin =
|
||||
reader.DeserializeVector<typename decltype(cell_to_children)::value_type>(begin, end);
|
||||
}
|
||||
|
||||
template <bool Q = UseShareMemory>
|
||||
typename std::enable_if<Q>::type InitializePointers(char *begin, const char *end)
|
||||
{
|
||||
auto level_offsets_size = *reinterpret_cast<std::uint64_t *>(begin);
|
||||
begin += sizeof(level_offsets_size);
|
||||
level_offsets.reset(begin, level_offsets_size);
|
||||
begin += sizeof(decltype(level_offsets[0])) * level_offsets_size;
|
||||
|
||||
auto partition_size = *reinterpret_cast<std::uint64_t *>(begin);
|
||||
begin += sizeof(partition_size);
|
||||
partition.reset(begin, partition_size);
|
||||
begin += sizeof(decltype(partition[0])) * partition_size;
|
||||
|
||||
auto level_to_children_offset_size = *reinterpret_cast<std::uint64_t *>(begin);
|
||||
begin += sizeof(level_to_children_offset_size);
|
||||
level_to_children_offset.reset(begin, level_to_children_offset_size);
|
||||
begin += sizeof(decltype(level_to_children_offset[0])) * level_to_children_offset_size;
|
||||
|
||||
auto cell_to_children_size = *reinterpret_cast<std::uint64_t *>(begin);
|
||||
begin += sizeof(cell_to_children_size);
|
||||
cell_to_children.reset(begin, cell_to_children_size);
|
||||
begin += sizeof(decltype(cell_to_children[0])) * level_to_children_offset_size;
|
||||
|
||||
BOOST_ASSERT(begin <= end);
|
||||
|
||||
level_masks = makeLevelMasks();
|
||||
bit_to_level = makeBitToLevel();
|
||||
}
|
||||
|
||||
template <bool Q = UseShareMemory>
|
||||
typename std::enable_if<!Q>::type Read(const boost::filesystem::path &path)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.DeserializeVector(level_offsets);
|
||||
reader.DeserializeVector(partition);
|
||||
reader.DeserializeVector(level_to_children_offset);
|
||||
reader.DeserializeVector(cell_to_children);
|
||||
|
||||
level_masks = makeLevelMasks();
|
||||
bit_to_level = makeBitToLevel();
|
||||
}
|
||||
|
||||
void Write(const boost::filesystem::path &path) const
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.SerializeVector(level_offsets);
|
||||
writer.SerializeVector(partition);
|
||||
writer.SerializeVector(level_to_children_offset);
|
||||
writer.SerializeVector(cell_to_children);
|
||||
}
|
||||
friend void partition::io::write<UseShareMemory>(const boost::filesystem::path &file,
|
||||
const MultiLevelPartitionImpl &mlp);
|
||||
|
||||
private:
|
||||
auto MakeLevelData(const std::vector<std::uint32_t> &lidx_to_num_cells)
|
||||
{
|
||||
std::uint32_t num_level = lidx_to_num_cells.size() + 1;
|
||||
auto offsets = MakeLevelOffsets(lidx_to_num_cells);
|
||||
auto masks = MakeLevelMasks(offsets, num_level);
|
||||
auto bits = MakeBitToLevel(offsets, num_level);
|
||||
return LevelData{num_level,
|
||||
offsets,
|
||||
masks,
|
||||
bits,
|
||||
{0}};
|
||||
}
|
||||
|
||||
inline std::size_t LevelIDToIndex(LevelID l) const { return l - 1; }
|
||||
|
||||
// We save the sentinel as last node in the partition information.
|
||||
@ -241,46 +196,45 @@ template <bool UseShareMemory> class PackedMultiLevelPartition final : public Mu
|
||||
{
|
||||
auto lidx = LevelIDToIndex(l);
|
||||
|
||||
auto shifted_id = cell_id << level_offsets[lidx];
|
||||
auto cleared_cell = partition[node] & ~level_masks[lidx];
|
||||
auto shifted_id = cell_id << level_data.lidx_to_offset[lidx];
|
||||
auto cleared_cell = partition[node] & ~level_data.lidx_to_mask[lidx];
|
||||
partition[node] = cleared_cell | shifted_id;
|
||||
}
|
||||
|
||||
// If we have N cells per level we need log_2 bits for every cell ID
|
||||
std::vector<std::uint8_t>
|
||||
makeLevelOffsets(const std::vector<std::uint32_t> &level_to_num_cells) const
|
||||
auto MakeLevelOffsets(const std::vector<std::uint32_t> &lidx_to_num_cells) const
|
||||
{
|
||||
std::vector<std::uint8_t> offsets;
|
||||
offsets.reserve(level_to_num_cells.size());
|
||||
std::array<std::uint8_t, MAX_NUM_LEVEL - 1> offsets;
|
||||
|
||||
auto lidx = 0UL;
|
||||
auto sum_bits = 0;
|
||||
for (auto num_cells : level_to_num_cells)
|
||||
for (auto num_cells : lidx_to_num_cells)
|
||||
{
|
||||
// bits needed to number all contained vertexes
|
||||
auto bits = static_cast<std::uint64_t>(std::ceil(std::log2(num_cells + 1)));
|
||||
offsets.push_back(sum_bits);
|
||||
offsets[lidx++] = sum_bits;
|
||||
sum_bits += bits;
|
||||
if (sum_bits > 64)
|
||||
{
|
||||
throw util::exception("Can't pack the partition information at level " +
|
||||
std::to_string(offsets.size()) +
|
||||
" into a 64bit integer. Would require " +
|
||||
std::to_string(sum_bits) + " bits.");
|
||||
throw util::exception(
|
||||
"Can't pack the partition information at level " + std::to_string(lidx) +
|
||||
" into a 64bit integer. Would require " + std::to_string(sum_bits) + " bits.");
|
||||
}
|
||||
}
|
||||
// sentinel
|
||||
offsets.push_back(sum_bits);
|
||||
offsets[lidx++] = sum_bits;
|
||||
BOOST_ASSERT(lidx < MAX_NUM_LEVEL);
|
||||
|
||||
return offsets;
|
||||
}
|
||||
|
||||
std::vector<PartitionID> makeLevelMasks() const
|
||||
auto MakeLevelMasks(const std::array<std::uint8_t, MAX_NUM_LEVEL - 1> &level_offsets, std::uint32_t num_level) const
|
||||
{
|
||||
std::vector<PartitionID> masks;
|
||||
masks.reserve(level_offsets.size());
|
||||
std::array<PartitionID, MAX_NUM_LEVEL - 1> masks;
|
||||
|
||||
auto lidx = 0UL;
|
||||
util::for_each_pair(level_offsets.begin(),
|
||||
level_offsets.end(),
|
||||
level_offsets.begin() + num_level,
|
||||
[&](const auto offset, const auto next_offset) {
|
||||
// create mask that has `bits` ones at its LSBs.
|
||||
// 000011
|
||||
@ -290,31 +244,30 @@ template <bool UseShareMemory> class PackedMultiLevelPartition final : public Mu
|
||||
BOOST_ASSERT(next_offset < NUM_PARTITION_BITS);
|
||||
PartitionID next_mask = (1UL << next_offset) - 1UL;
|
||||
// 001100
|
||||
masks.push_back(next_mask ^ mask);
|
||||
masks[lidx++] = next_mask ^ mask;
|
||||
});
|
||||
|
||||
return masks;
|
||||
}
|
||||
|
||||
std::array<LevelID, NUM_PARTITION_BITS> makeBitToLevel() const
|
||||
auto MakeBitToLevel(const std::array<std::uint8_t, MAX_NUM_LEVEL - 1> &level_offsets, std::uint32_t num_level) const
|
||||
{
|
||||
std::array<LevelID, NUM_PARTITION_BITS> bit_to_level;
|
||||
|
||||
LevelID l = 1;
|
||||
for (auto bits : level_offsets)
|
||||
for (auto l = 1u; l < num_level; ++l)
|
||||
{
|
||||
auto bits = level_offsets[l-1];
|
||||
// set all bits to point to the correct level.
|
||||
for (auto idx = bits; idx < NUM_PARTITION_BITS; ++idx)
|
||||
{
|
||||
bit_to_level[idx] = l;
|
||||
}
|
||||
l++;
|
||||
}
|
||||
|
||||
return bit_to_level;
|
||||
}
|
||||
|
||||
void initializePartitionIDs(const std::vector<std::vector<CellID>> &partitions)
|
||||
void InitializePartitionIDs(const std::vector<std::vector<CellID>> &partitions)
|
||||
{
|
||||
auto num_nodes = partitions.front().size();
|
||||
std::vector<NodeID> permutation(num_nodes);
|
||||
@ -370,14 +323,13 @@ template <bool UseShareMemory> class PackedMultiLevelPartition final : public Mu
|
||||
level--;
|
||||
}
|
||||
|
||||
// level 1 does not have child cells
|
||||
level_to_children_offset.push_back(0);
|
||||
level_data.lidx_to_children_offsets[0] = 0;
|
||||
|
||||
for (auto level_idx = 0UL; level_idx < partitions.size() - 1; ++level_idx)
|
||||
{
|
||||
const auto &parent_partition = partitions[level_idx + 1];
|
||||
|
||||
level_to_children_offset.push_back(cell_to_children.size());
|
||||
level_data.lidx_to_children_offsets[level_idx+1] = cell_to_children.size();
|
||||
|
||||
CellID last_parent_id = parent_partition[permutation.front()];
|
||||
cell_to_children.push_back(GetCell(level_idx + 1, permutation.front()));
|
||||
@ -396,14 +348,13 @@ template <bool UseShareMemory> class PackedMultiLevelPartition final : public Mu
|
||||
}
|
||||
}
|
||||
|
||||
typename util::ShM<std::uint8_t, UseShareMemory>::vector level_offsets;
|
||||
typename util::ShM<PartitionID, UseShareMemory>::vector partition;
|
||||
typename util::ShM<std::uint32_t, UseShareMemory>::vector level_to_children_offset;
|
||||
typename util::ShM<CellID, UseShareMemory>::vector cell_to_children;
|
||||
std::vector<PartitionID> level_masks;
|
||||
std::array<LevelID, NUM_PARTITION_BITS> bit_to_level;
|
||||
//! this is always owned by this class because it is so small
|
||||
LevelData level_data;
|
||||
Vector<PartitionID> partition;
|
||||
Vector<CellID> cell_to_children;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -45,6 +45,9 @@ OSRM::OSRM(engine::EngineConfig &config)
|
||||
case EngineConfig::Algorithm::CoreCH:
|
||||
engine_ = std::make_unique<engine::Engine<engine::algorithm::CoreCH>>(config);
|
||||
break;
|
||||
case EngineConfig::Algorithm::MLD:
|
||||
engine_ = std::make_unique<engine::Engine<engine::algorithm::MLD>>(config);
|
||||
break;
|
||||
default:
|
||||
util::exception("Algorithm not implemented!");
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "partition/edge_based_graph_reader.hpp"
|
||||
#include "partition/node_based_graph_to_edge_based_graph_mapping_reader.hpp"
|
||||
#include "partition/recursive_bisection.hpp"
|
||||
#include "partition/io.hpp"
|
||||
|
||||
#include "util/cell_storage.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
@ -21,7 +22,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
|
||||
#include "util/geojson_debug_logger.hpp"
|
||||
#include "util/geojson_debug_policies.hpp"
|
||||
@ -203,7 +203,7 @@ int Partitioner::Run(const PartitionConfig &config)
|
||||
// split bisection id bits into groups starting from SCC and stop at level 1
|
||||
BOOST_ASSERT(recursive_bisection.SCCDepth() != 0);
|
||||
int mask_from = sizeof(BisectionID) * CHAR_BIT - recursive_bisection.SCCDepth();
|
||||
boost::container::small_vector<BisectionID, 8> level_masks;
|
||||
std::vector<BisectionID> level_masks;
|
||||
for (int mask_to = sizeof(BisectionID) * CHAR_BIT; mask_to > first_nonzero_position;
|
||||
mask_to = mask_from, mask_from -= 3) // TODO: find better grouping
|
||||
{
|
||||
@ -250,7 +250,7 @@ int Partitioner::Run(const PartitionConfig &config)
|
||||
}
|
||||
|
||||
TIMER_START(packed_mlp);
|
||||
osrm::util::PackedMultiLevelPartition<false> mlp{partitions, level_to_num_cells};
|
||||
osrm::util::MultiLevelPartition mlp{partitions, level_to_num_cells};
|
||||
TIMER_STOP(packed_mlp);
|
||||
util::Log() << "PackedMultiLevelPartition constructed in " << TIMER_SEC(packed_mlp)
|
||||
<< " seconds";
|
||||
@ -261,7 +261,7 @@ int Partitioner::Run(const PartitionConfig &config)
|
||||
util::Log() << "CellStorage constructed in " << TIMER_SEC(cell_storage) << " seconds";
|
||||
|
||||
TIMER_START(writing_mld_data);
|
||||
mlp.Write(config.mld_partition_path);
|
||||
io::write(config.mld_partition_path, mlp);
|
||||
storage.Write(config.mld_storage_path);
|
||||
TIMER_STOP(writing_mld_data);
|
||||
util::Log() << "MLD data writing took " << TIMER_SEC(writing_mld_data) << " seconds";
|
||||
|
@ -400,12 +400,21 @@ void Storage::PopulateLayout(DataLayout &layout)
|
||||
// Loading MLD Data
|
||||
if (boost::filesystem::exists(config.mld_partition_path))
|
||||
{
|
||||
auto mld_partition_size = util::PackedMultiLevelPartition<true>().GetRequiredMemorySize(
|
||||
config.mld_partition_path);
|
||||
layout.SetBlockSize<char>(DataLayout::MLD_CELL_PARTITION, mld_partition_size);
|
||||
io::FileReader reader(config.mld_partition_path, io::FileReader::VerifyFingerprint);
|
||||
|
||||
reader.Skip<util::MultiLevelPartition::LevelData>(1);
|
||||
layout.SetBlockSize<util::MultiLevelPartition::LevelData>(DataLayout::MLD_LEVEL_DATA, 1);
|
||||
const auto partition_entries_count = reader.ReadVectorSize<util::PartitionID>();
|
||||
layout.SetBlockSize<util::PartitionID>(DataLayout::MLD_PARTITION, partition_entries_count);
|
||||
const auto children_entries_count = reader.ReadVectorSize<util::CellID>();
|
||||
layout.SetBlockSize<util::CellID>(DataLayout::MLD_CELL_TO_CHILDREN, children_entries_count);
|
||||
}
|
||||
else
|
||||
layout.SetBlockSize<char>(DataLayout::MLD_CELL_PARTITION, 0);
|
||||
{
|
||||
layout.SetBlockSize<util::MultiLevelPartition::LevelData>(DataLayout::MLD_LEVEL_DATA, 0);
|
||||
layout.SetBlockSize<util::PartitionID>(DataLayout::MLD_PARTITION, 0);
|
||||
layout.SetBlockSize<util::CellID>(DataLayout::MLD_CELL_TO_CHILDREN, 0);
|
||||
}
|
||||
|
||||
if (boost::filesystem::exists(config.mld_storage_path))
|
||||
{
|
||||
@ -866,13 +875,17 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
|
||||
|
||||
{
|
||||
// Loading MLD Data
|
||||
const auto mld_partition_ptr =
|
||||
layout.GetBlockPtr<char, true>(memory_ptr, DataLayout::MLD_CELL_PARTITION);
|
||||
const auto mld_partition_size = layout.GetBlockSize(DataLayout::MLD_CELL_PARTITION);
|
||||
if (boost::filesystem::exists(config.mld_partition_path))
|
||||
{
|
||||
util::PackedMultiLevelPartition<true>().Read(
|
||||
config.mld_partition_path, mld_partition_ptr, mld_partition_ptr + mld_partition_size);
|
||||
auto mld_level_data_ptr = layout.GetBlockPtr<util::MultiLevelPartition::LevelData, true>(memory_ptr, DataLayout::MLD_LEVEL_DATA);
|
||||
auto mld_partition_ptr = layout.GetBlockPtr<util::PartitionID, true>(memory_ptr, DataLayout::MLD_PARTITION);
|
||||
auto mld_chilren_ptr = layout.GetBlockPtr<util::CellID, true>(memory_ptr, DataLayout::MLD_CELL_TO_CHILDREN);
|
||||
|
||||
io::FileReader reader(config.mld_partition_path, io::FileReader::VerifyFingerprint);
|
||||
|
||||
reader.ReadInto(mld_level_data_ptr);
|
||||
reader.ReadInto(mld_partition_ptr, layout.GetBlockEntries(DataLayout::MLD_PARTITION));
|
||||
reader.ReadInto(mld_chilren_ptr, layout.GetBlockEntries(DataLayout::MLD_CELL_TO_CHILDREN));
|
||||
}
|
||||
|
||||
const auto mld_cell_storage_ptr =
|
||||
|
@ -20,8 +20,8 @@ StorageConfig::StorageConfig(const boost::filesystem::path &base)
|
||||
names_data_path{base.string() + ".names"}, properties_path{base.string() + ".properties"},
|
||||
intersection_class_path{base.string() + ".icd"}, turn_lane_data_path{base.string() + ".tld"},
|
||||
turn_lane_description_path{base.string() + ".tls"},
|
||||
mld_partition_path{base.string() + ".mld_partition"},
|
||||
mld_storage_path{base.string() + ".mld_storage"}
|
||||
mld_partition_path{base.string() + ".partition"},
|
||||
mld_storage_path{base.string() + ".cell"}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,8 @@ EngineConfig::Algorithm stringToAlgorithm(const std::string &algorithm)
|
||||
return EngineConfig::Algorithm::CH;
|
||||
if (algorithm == "CoreCH")
|
||||
return EngineConfig::Algorithm::CoreCH;
|
||||
if (algorithm == "MLD")
|
||||
return EngineConfig::Algorithm::MLD;
|
||||
throw util::exception("Invalid algorithm name: " + algorithm);
|
||||
}
|
||||
|
||||
@ -100,7 +102,7 @@ inline unsigned generateServerProgramOptions(const int argc,
|
||||
"Load data from shared memory") //
|
||||
("algorithm,a",
|
||||
value<std::string>(&algorithm)->default_value("CH"),
|
||||
"Algorithm to use for the data. Can be CH, CoreCH") //
|
||||
"Algorithm to use for the data. Can be CH, CoreCH, MLD.") //
|
||||
("max-viaroute-size",
|
||||
value<int>(&max_locations_viaroute)->default_value(500),
|
||||
"Max. locations supported in viaroute query") //
|
||||
|
@ -16,32 +16,6 @@
|
||||
using namespace osrm;
|
||||
using namespace osrm::util;
|
||||
|
||||
class MockMLP final : public MultiLevelPartition
|
||||
{
|
||||
public:
|
||||
CellID GetCell(LevelID level, NodeID node) const { return levels[level - 1][node]; };
|
||||
|
||||
LevelID GetHighestDifferentLevel(NodeID, NodeID) const { return 3; };
|
||||
LevelID GetQueryLevel(NodeID, NodeID, NodeID) const { return 3; };
|
||||
|
||||
std::uint8_t GetNumberOfLevels() const { return levels.size() + 1; }
|
||||
|
||||
std::uint32_t GetNumberOfCells(LevelID level) const
|
||||
{
|
||||
auto max_id = 0;
|
||||
for (auto cell : levels[level - 1])
|
||||
max_id = std::max<CellID>(max_id, cell);
|
||||
return max_id + 1;
|
||||
}
|
||||
|
||||
CellID BeginChildren(LevelID, CellID) const { return 0; }
|
||||
CellID EndChildren(LevelID, CellID) const { return 0; }
|
||||
|
||||
MockMLP(std::vector<std::vector<CellID>> levels_) : levels(std::move(levels_)) {}
|
||||
|
||||
std::vector<std::vector<CellID>> levels;
|
||||
};
|
||||
|
||||
struct MockEdge
|
||||
{
|
||||
NodeID start;
|
||||
@ -84,7 +58,7 @@ BOOST_AUTO_TEST_CASE(mutable_cell_storage)
|
||||
std::vector<CellID> l2{{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3}};
|
||||
std::vector<CellID> l3{{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}};
|
||||
std::vector<CellID> l4{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
MockMLP mlp{{l1, l2, l3, l4}};
|
||||
MultiLevelPartition mlp{{l1, l2, l3, l4}, {2, 4, 8, 12}};
|
||||
|
||||
std::vector<MockEdge> edges = {
|
||||
// edges sorted into border/internal by level
|
||||
@ -193,7 +167,7 @@ BOOST_AUTO_TEST_CASE(immutable_cell_storage)
|
||||
std::vector<CellID> l2{{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3}};
|
||||
std::vector<CellID> l3{{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}};
|
||||
std::vector<CellID> l4{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
MockMLP mlp{{l1, l2, l3, l4}};
|
||||
MultiLevelPartition mlp{{l1, l2, l3, l4}, {2, 4, 8, 12}};
|
||||
|
||||
std::vector<MockEdge> edges = {
|
||||
// edges sorted into border/internal by level
|
||||
|
@ -17,14 +17,83 @@ using namespace osrm::util;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(multi_level_partition_tests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(packed_mlp)
|
||||
BOOST_AUTO_TEST_CASE(mlp_one)
|
||||
{
|
||||
// node: 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
std::vector<CellID> l1{{4, 4, 2, 2, 1, 1, 3, 3, 2, 2, 5, 5}};
|
||||
MultiLevelPartition mlp{{l1}, {6}};
|
||||
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 0), mlp.GetCell(1, 1));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 2), mlp.GetCell(1, 3));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 4), mlp.GetCell(1, 5));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 6), mlp.GetCell(1, 7));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 8), mlp.GetCell(1, 9));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 10), mlp.GetCell(1, 11));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(mlp_shuffled)
|
||||
{
|
||||
// node: 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
std::vector<CellID> l1{{4, 4, 2, 2, 1, 1, 3, 3, 2, 2, 5, 5}};
|
||||
std::vector<CellID> l2{{3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 0, 0}};
|
||||
std::vector<CellID> l3{{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}};
|
||||
std::vector<CellID> l4{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
MultiLevelPartition mlp{{l1, l2, l3, l4}, {6, 4, 2, 1}};
|
||||
|
||||
BOOST_CHECK_EQUAL(mlp.GetNumberOfCells(1), 6);
|
||||
BOOST_CHECK_EQUAL(mlp.GetNumberOfCells(2), 4);
|
||||
BOOST_CHECK_EQUAL(mlp.GetNumberOfCells(3), 2);
|
||||
BOOST_CHECK_EQUAL(mlp.GetNumberOfCells(4), 1);
|
||||
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 0), mlp.GetCell(1, 1));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 2), mlp.GetCell(1, 3));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 4), mlp.GetCell(1, 5));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 6), mlp.GetCell(1, 7));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 8), mlp.GetCell(1, 9));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(1, 10), mlp.GetCell(1, 11));
|
||||
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(2, 0), mlp.GetCell(2, 1));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(2, 0), mlp.GetCell(2, 2));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(2, 0), mlp.GetCell(2, 3));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(2, 4), mlp.GetCell(2, 5));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(2, 4), mlp.GetCell(2, 6));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(2, 4), mlp.GetCell(2, 7));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(2, 8), mlp.GetCell(2, 9));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(2, 10), mlp.GetCell(2, 11));
|
||||
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(3, 0), mlp.GetCell(3, 1));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(3, 0), mlp.GetCell(3, 2));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(3, 0), mlp.GetCell(3, 3));
|
||||
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(3, 4), mlp.GetCell(3, 5));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(3, 4), mlp.GetCell(3, 6));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(3, 4), mlp.GetCell(3, 7));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(3, 4), mlp.GetCell(3, 8));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(3, 4), mlp.GetCell(3, 9));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(3, 4), mlp.GetCell(3, 10));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(3, 4), mlp.GetCell(3, 11));
|
||||
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 1));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 2));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 3));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 4));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 5));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 6));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 7));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 8));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 9));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 10));
|
||||
BOOST_CHECK_EQUAL(mlp.GetCell(4, 0), mlp.GetCell(4, 11));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(mlp_sorted)
|
||||
{
|
||||
// node: 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
std::vector<CellID> l1{{0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5}};
|
||||
std::vector<CellID> l2{{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3}};
|
||||
std::vector<CellID> l3{{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}};
|
||||
std::vector<CellID> l4{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
PackedMultiLevelPartition<false> mlp{{l1, l2, l3, l4}, {6, 4, 2, 1}};
|
||||
MultiLevelPartition mlp{{l1, l2, l3, l4}, {6, 4, 2, 1}};
|
||||
|
||||
BOOST_CHECK_EQUAL(mlp.GetNumberOfCells(1), 6);
|
||||
BOOST_CHECK_EQUAL(mlp.GetNumberOfCells(2), 4);
|
||||
|
Loading…
Reference in New Issue
Block a user