Resurrect Flat Map + Binary Search commit from PR 2412
This commit is contained in:
		
							parent
							
								
									d1bc32fb31
								
							
						
					
					
						commit
						ce5ae411c1
					
				| @ -29,7 +29,9 @@ | |||||||
| #include <tbb/parallel_for_each.h> | #include <tbb/parallel_for_each.h> | ||||||
| #include <tbb/parallel_invoke.h> | #include <tbb/parallel_invoke.h> | ||||||
| #include <tbb/parallel_sort.h> | #include <tbb/parallel_sort.h> | ||||||
|  | #include <tbb/spin_mutex.h> | ||||||
| 
 | 
 | ||||||
|  | #include <algorithm> | ||||||
| #include <bitset> | #include <bitset> | ||||||
| #include <cstdint> | #include <cstdint> | ||||||
| #include <fstream> | #include <fstream> | ||||||
| @ -148,12 +150,45 @@ int Contractor::Run() | |||||||
| namespace | namespace | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| // Convenience aliases. TODO: make actual types at some point in time.
 | struct Segment final | ||||||
|  | { | ||||||
|  |     OSMNodeID from, to; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| using Segment = std::pair<OSMNodeID, OSMNodeID>; | struct SpeedSource final | ||||||
| using SegmentHasher = std::hash<Segment>; | { | ||||||
| using SpeedSource = std::pair<unsigned, std::uint8_t>; |     unsigned speed; | ||||||
| using SegmentSpeedSourceMap = tbb::concurrent_unordered_map<Segment, SpeedSource, SegmentHasher>; |     std::uint8_t source; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct SegmentSpeedSource final | ||||||
|  | { | ||||||
|  |     Segment segment; | ||||||
|  |     SpeedSource speed_source; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | using SegmentSpeedSourceFlatMap = std::vector<SegmentSpeedSource>; | ||||||
|  | 
 | ||||||
|  | // Binary Search over a flattened key,val Segment storage
 | ||||||
|  | SegmentSpeedSourceFlatMap::iterator find(SegmentSpeedSourceFlatMap &map, const Segment &key) | ||||||
|  | { | ||||||
|  |     const auto last = end(map); | ||||||
|  | 
 | ||||||
|  |     const auto by_segment = [](const SegmentSpeedSource &lhs, const SegmentSpeedSource &rhs) { | ||||||
|  |         return std::tie(lhs.segment.from, lhs.segment.to) > | ||||||
|  |                std::tie(rhs.segment.from, rhs.segment.to); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     auto it = std::lower_bound(begin(map), last, SegmentSpeedSource{key, {0, 0}}, by_segment); | ||||||
|  | 
 | ||||||
|  |     if (it != last && (std::tie(it->segment.from, it->segment.to) == std::tie(key.from, key.to))) | ||||||
|  |         return it; | ||||||
|  | 
 | ||||||
|  |     return last; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Convenience aliases. TODO: make actual types at some point in time.
 | ||||||
|  | // TODO: turn penalties need flat map + binary search optimization, take a look at segment speeds
 | ||||||
| 
 | 
 | ||||||
| using Turn = std::tuple<OSMNodeID, OSMNodeID, OSMNodeID>; | using Turn = std::tuple<OSMNodeID, OSMNodeID, OSMNodeID>; | ||||||
| using TurnHasher = std::hash<Turn>; | using TurnHasher = std::hash<Turn>; | ||||||
| @ -162,11 +197,16 @@ using TurnPenaltySourceMap = tbb::concurrent_unordered_map<Turn, PenaltySource, | |||||||
| 
 | 
 | ||||||
| // Functions for parsing files and creating lookup tables
 | // Functions for parsing files and creating lookup tables
 | ||||||
| 
 | 
 | ||||||
| SegmentSpeedSourceMap | SegmentSpeedSourceFlatMap | ||||||
| parse_segment_lookup_from_csv_files(const std::vector<std::string> &segment_speed_filenames) | parse_segment_lookup_from_csv_files(const std::vector<std::string> &segment_speed_filenames) | ||||||
| { | { | ||||||
|     // TODO: shares code with turn penalty lookup parse function
 |     // TODO: shares code with turn penalty lookup parse function
 | ||||||
|     SegmentSpeedSourceMap map; | 
 | ||||||
|  |     using Mutex = tbb::spin_mutex; | ||||||
|  | 
 | ||||||
|  |     // Loaded and parsed in parallel, at the end we combine results in a flattened map-ish view
 | ||||||
|  |     SegmentSpeedSourceFlatMap flatten; | ||||||
|  |     Mutex flatten_mutex; | ||||||
| 
 | 
 | ||||||
|     const auto parse_segment_speed_file = [&](const std::size_t idx) { |     const auto parse_segment_speed_file = [&](const std::size_t idx) { | ||||||
|         const auto file_id = idx + 1; // starts at one, zero means we assigned the weight
 |         const auto file_id = idx + 1; // starts at one, zero means we assigned the weight
 | ||||||
| @ -176,6 +216,8 @@ parse_segment_lookup_from_csv_files(const std::vector<std::string> &segment_spee | |||||||
|         if (!segment_speed_file) |         if (!segment_speed_file) | ||||||
|             throw util::exception{"Unable to open segment speed file " + filename}; |             throw util::exception{"Unable to open segment speed file " + filename}; | ||||||
| 
 | 
 | ||||||
|  |         SegmentSpeedSourceFlatMap local; | ||||||
|  | 
 | ||||||
|         std::uint64_t from_node_id{}; |         std::uint64_t from_node_id{}; | ||||||
|         std::uint64_t to_node_id{}; |         std::uint64_t to_node_id{}; | ||||||
|         unsigned speed{}; |         unsigned speed{}; | ||||||
| @ -195,14 +237,43 @@ parse_segment_lookup_from_csv_files(const std::vector<std::string> &segment_spee | |||||||
|             if (!ok || it != last) |             if (!ok || it != last) | ||||||
|                 throw util::exception{"Segment speed file " + filename + " malformed"}; |                 throw util::exception{"Segment speed file " + filename + " malformed"}; | ||||||
| 
 | 
 | ||||||
|             map[std::make_pair(OSMNodeID(from_node_id), OSMNodeID(to_node_id))] = |             SegmentSpeedSource val{ | ||||||
|                 std::make_pair(speed, file_id); |                 {static_cast<OSMNodeID>(from_node_id), static_cast<OSMNodeID>(to_node_id)}, | ||||||
|  |                 {speed, static_cast<std::uint8_t>(file_id)}}; | ||||||
|  | 
 | ||||||
|  |             local.push_back(std::move(val)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         { | ||||||
|  |             Mutex::scoped_lock _{flatten_mutex}; | ||||||
|  | 
 | ||||||
|  |             flatten.insert(end(flatten), std::make_move_iterator(begin(local)), | ||||||
|  |                            std::make_move_iterator(end(local))); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     tbb::parallel_for(std::size_t{0}, segment_speed_filenames.size(), parse_segment_speed_file); |     tbb::parallel_for(std::size_t{0}, segment_speed_filenames.size(), parse_segment_speed_file); | ||||||
| 
 | 
 | ||||||
|     return map; |     // With flattened map-ish view of all the files, sort and unique them on from,to,source
 | ||||||
|  |     // The greater '>' is used here since we want to give files later on higher precedence
 | ||||||
|  |     const auto sort_by = [](const SegmentSpeedSource &lhs, const SegmentSpeedSource &rhs) { | ||||||
|  |         return std::tie(lhs.segment.from, lhs.segment.to, lhs.speed_source.source) > | ||||||
|  |                std::tie(rhs.segment.from, rhs.segment.to, rhs.speed_source.source); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     std::stable_sort(begin(flatten), end(flatten), sort_by); | ||||||
|  | 
 | ||||||
|  |     // Unique only on from,to to take the source precedence into account and remove duplicates
 | ||||||
|  |     const auto unique_by = [](const SegmentSpeedSource &lhs, const SegmentSpeedSource &rhs) { | ||||||
|  |         return std::tie(lhs.segment.from, lhs.segment.to) == | ||||||
|  |                std::tie(rhs.segment.from, rhs.segment.to); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     const auto it = std::unique(begin(flatten), end(flatten), unique_by); | ||||||
|  | 
 | ||||||
|  |     flatten.erase(it, end(flatten)); | ||||||
|  | 
 | ||||||
|  |     return flatten; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TurnPenaltySourceMap | TurnPenaltySourceMap | ||||||
| @ -305,7 +376,7 @@ std::size_t Contractor::LoadEdgeExpandedGraph( | |||||||
|     util::SimpleLogger().Write() << "Reading " << number_of_edges |     util::SimpleLogger().Write() << "Reading " << number_of_edges | ||||||
|                                  << " edges from the edge based graph"; |                                  << " edges from the edge based graph"; | ||||||
| 
 | 
 | ||||||
|     SegmentSpeedSourceMap segment_speed_lookup; |     SegmentSpeedSourceFlatMap segment_speed_lookup; | ||||||
|     TurnPenaltySourceMap turn_penalty_lookup; |     TurnPenaltySourceMap turn_penalty_lookup; | ||||||
| 
 | 
 | ||||||
|     const auto parse_segment_speeds = [&] { |     const auto parse_segment_speeds = [&] { | ||||||
| @ -446,18 +517,18 @@ std::size_t Contractor::LoadEdgeExpandedGraph( | |||||||
|                         util::Coordinate{u->lon, u->lat}, util::Coordinate{v->lon, v->lat}); |                         util::Coordinate{u->lon, u->lat}, util::Coordinate{v->lon, v->lat}); | ||||||
| 
 | 
 | ||||||
|                     auto forward_speed_iter = |                     auto forward_speed_iter = | ||||||
|                         segment_speed_lookup.find(std::make_pair(u->node_id, v->node_id)); |                         find(segment_speed_lookup, Segment{u->node_id, v->node_id}); | ||||||
|                     if (forward_speed_iter != segment_speed_lookup.end()) |                     if (forward_speed_iter != segment_speed_lookup.end()) | ||||||
|                     { |                     { | ||||||
|                         int new_segment_weight = std::max( |                         int new_segment_weight = | ||||||
|                             1, |                             std::max(1, static_cast<int>(std::floor( | ||||||
|                             static_cast<int>(std::floor( |                                             (segment_length * 10.) / | ||||||
|                                 (segment_length * 10.) / (forward_speed_iter->second.first / 3.6) + |                                                 (forward_speed_iter->speed_source.speed / 3.6) + | ||||||
|                                             .5))); |                                             .5))); | ||||||
|                         m_geometry_list[forward_begin + leaf_object.fwd_segment_position].weight = |                         m_geometry_list[forward_begin + leaf_object.fwd_segment_position].weight = | ||||||
|                             new_segment_weight; |                             new_segment_weight; | ||||||
|                         m_geometry_datasource[forward_begin + leaf_object.fwd_segment_position] = |                         m_geometry_datasource[forward_begin + leaf_object.fwd_segment_position] = | ||||||
|                             forward_speed_iter->second.second; |                             forward_speed_iter->speed_source.source; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if (leaf_object.reverse_packed_geometry_id != SPECIAL_EDGEID) |                 if (leaf_object.reverse_packed_geometry_id != SPECIAL_EDGEID) | ||||||
| @ -488,18 +559,18 @@ std::size_t Contractor::LoadEdgeExpandedGraph( | |||||||
|                         util::Coordinate{u->lon, u->lat}, util::Coordinate{v->lon, v->lat}); |                         util::Coordinate{u->lon, u->lat}, util::Coordinate{v->lon, v->lat}); | ||||||
| 
 | 
 | ||||||
|                     auto reverse_speed_iter = |                     auto reverse_speed_iter = | ||||||
|                         segment_speed_lookup.find(std::make_pair(u->node_id, v->node_id)); |                         find(segment_speed_lookup, Segment{u->node_id, v->node_id}); | ||||||
|                     if (reverse_speed_iter != segment_speed_lookup.end()) |                     if (reverse_speed_iter != segment_speed_lookup.end()) | ||||||
|                     { |                     { | ||||||
|                         int new_segment_weight = std::max( |                         int new_segment_weight = | ||||||
|                             1, |                             std::max(1, static_cast<int>(std::floor( | ||||||
|                             static_cast<int>(std::floor( |                                             (segment_length * 10.) / | ||||||
|                                 (segment_length * 10.) / (reverse_speed_iter->second.first / 3.6) + |                                                 (reverse_speed_iter->speed_source.speed / 3.6) + | ||||||
|                                             .5))); |                                             .5))); | ||||||
|                         m_geometry_list[reverse_begin + rev_segment_position].weight = |                         m_geometry_list[reverse_begin + rev_segment_position].weight = | ||||||
|                             new_segment_weight; |                             new_segment_weight; | ||||||
|                         m_geometry_datasource[reverse_begin + rev_segment_position] = |                         m_geometry_datasource[reverse_begin + rev_segment_position] = | ||||||
|                             reverse_speed_iter->second.second; |                             reverse_speed_iter->speed_source.source; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -594,16 +665,17 @@ std::size_t Contractor::LoadEdgeExpandedGraph( | |||||||
|                 edge_segment_input_stream.read(reinterpret_cast<char *>(&segment_weight), |                 edge_segment_input_stream.read(reinterpret_cast<char *>(&segment_weight), | ||||||
|                                                sizeof(segment_weight)); |                                                sizeof(segment_weight)); | ||||||
| 
 | 
 | ||||||
|                 auto speed_iter = segment_speed_lookup.find( |                 auto speed_iter = | ||||||
|                     std::make_pair(previous_osm_node_id, this_osm_node_id)); |                     find(segment_speed_lookup, Segment{previous_osm_node_id, this_osm_node_id}); | ||||||
|                 if (speed_iter != segment_speed_lookup.end()) |                 if (speed_iter != segment_speed_lookup.end()) | ||||||
|                 { |                 { | ||||||
|                     // This sets the segment weight using the same formula as the
 |                     // This sets the segment weight using the same formula as the
 | ||||||
|                     // EdgeBasedGraphFactory for consistency.  The *why* of this formula
 |                     // EdgeBasedGraphFactory for consistency.  The *why* of this formula
 | ||||||
|                     // is lost in the annals of time.
 |                     // is lost in the annals of time.
 | ||||||
|                     int new_segment_weight = std::max( |                     int new_segment_weight = std::max( | ||||||
|                         1, static_cast<int>(std::floor( |                         1, | ||||||
|                                (segment_length * 10.) / (speed_iter->second.first / 3.6) + .5))); |                         static_cast<int>(std::floor( | ||||||
|  |                             (segment_length * 10.) / (speed_iter->speed_source.speed / 3.6) + .5))); | ||||||
|                     new_weight += new_segment_weight; |                     new_weight += new_segment_weight; | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user