Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve speed of Map Matching #5060

Merged
merged 8 commits into from
Aug 2, 2018
Merged

Improve speed of Map Matching #5060

merged 8 commits into from
Aug 2, 2018

Conversation

TheMarex
Copy link
Member

@TheMarex TheMarex commented Apr 27, 2018

Issue

This PR optimizes the map matching plugin for speed. It uses two things to do that:

  • The distance annotation work and improved distance calculation speed
  • Caching the forward search space for every state transition.

For my test trace this yielded a speedup of 2.

Measurements

branch avg. time speedup
master 61.18 1.0
faster_mapmatching 35.44 1.81

image

Tasklist

  • run benchmark on real traces with bigger dataset
  • review
  • adjust for comments
  • cherry pick to release branch

@TheMarex TheMarex force-pushed the faster_mapmatching branch from 0eab1f2 to f8c478f Compare June 27, 2018 20:40
@TheMarex TheMarex force-pushed the faster_mapmatching branch from f8c478f to 641906d Compare July 20, 2018 12:40
Copy link
Member

@daniel-j-h daniel-j-h left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some Travis builds are timing out; and looks like a test is failing. Left some comments inline.

| 4321 | 1.00027,1,1.000135,1 | 15.013264 | 1.5 | 1.5 | 1.5 |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do these tests change when the PR says it's only optimizing the map-matching performance?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It impacts numeric stability a little bit, which can leas to different matchings being chosen.

namespace detail
{
template <typename Algorithm>
void insertSourceInHeap(typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, why only template the algorithm and not simply the heap? Does it make sense to restricti it to a specific heap impl.?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need this in order to provide overloads for the normal QueryHeap and ManyToMany heap.

}
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below: looks like we are doing the same for all algorithms? Do we need to be specific about the algorithm then or can we simply have generic functions passing the parameters on to the downstream functions?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that we can't infer the algorithm from the SearchEngineData since we only pass in sub-type typename SearchEngineData<Algorithm>::QueryHeap. I would love to do this with automatic code generation but I did not find a way to do it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm can you simply put a member type into the sub-class as in vector<T>::value_type ?

}

template <typename Heap>
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we template the heap in contrast to above where we keep the heap impl. fixed and only template the algorithm - why?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This a generic wrapper that dispatches to the overloaded functions for insert{Source/Target}InHeap.

void adjustPathDistanceToPhantomNodes(const std::vector<NodeID> &path,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
EdgeDistance &distance);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out-ref? can you return by value?

}
}

// guard against underflow errors caused by rounding
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be an assert here checking for an epsilon making sure it's only due to rounding and not due to bugs in our code? Otherwise a negative erroneous distance will be silently ignored here.

@@ -110,10 +110,14 @@ void search(SearchEngineData<Algorithm> & /*engine_working_data*/,
weight = weight_upper_bound;

// get offset to account for offsets on phantom nodes on compressed edges
const auto min_edge_offset = std::min(0, forward_heap.MinKey());
BOOST_ASSERT(min_edge_offset <= 0);
auto min_edge_offset = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be int - do we want to be explicit about the type here?

unpackPath(facade,
packed_path.begin(),
packed_path.end(),
[&](std::pair<NodeID, NodeID> &edge, const auto &) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const ref for the pair? Maybe const auto& even

unpacked_nodes.push_back(edge.second);
});

for (auto node_iter = unpacked_nodes.begin(); node_iter != std::prev(unpacked_nodes.end());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: last and accumulate


// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
const constexpr long double EARTH_RADIUS = 6372797.560856;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this has to be long double? Why do we need it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right up to 15 digits should be fine.

@TheMarex TheMarex force-pushed the faster_mapmatching branch from 2f84f37 to edd334d Compare July 22, 2018 15:30
@TheMarex
Copy link
Member Author

@daniel-j-h Addressed your PR comments and added a measurements for the speedups on Berlin.

Copy link
Member

@daniel-j-h daniel-j-h left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like cucumber is currently still failing and you need to re-run clang-format. Otherwise 👍 🚢

@TheMarex TheMarex added this to the 5.18.1 milestone Jul 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants