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

Use node weights instead of edge weights in MLD algorithm #5049

Merged
merged 9 commits into from
Apr 28, 2018

Conversation

oxidase
Copy link
Contributor

@oxidase oxidase commented Apr 23, 2018

Issue

PR implements issue #5027 and can be merged after review, but if #4876 will be merged before then the commit 061a314 won't be required.

PR removes weight and duration, forward, backward members from EdgeBasedGraphEdgeData and adds a new customizer::MultiLevelGraph that has node_weights, node_weights, is_forward_edge, is_backward_edge vectors that are used now to compute edge weights and durations as a sum of node weights and turn penalties. The size of .osrm.mldgr files for california-latest.osm.pbf changes from 382468608 to 254924800 bytes or 33% reduction.

Performance check on california-latest.osm.pbf with random A->B routes does not show regression:
compare

In addition PR fixes two issues:

  • e637d69 adds an exception throw if a shared region is not found to prevent UB
  • cda8b1b uses the sign bit of node weight to mark oneway streets and correctly set node weight value to INVALID_EDGE_WEIGHT if the value was updated. The change must fix bugs with missing routes after traffic updates in CH algorithm.

/cc @TheMarex @freenerd

Tasklist

Requirements / Relations

#4876

@oxidase oxidase requested a review from TheMarex April 23, 2018 15:21
@oxidase
Copy link
Contributor Author

oxidase commented Apr 24, 2018

For europe-latest.osm.pbf dataset:

  • master

    • static part has a size of 12345436828 bytes
    • updateable part has a size of 18792362496 bytes
  • branch

    • static part has a size of 12345429128 bytes
    • updateable part has a size of 17417163264bytes

PR reduces the complete dataset size by 5% and the updateable part of the dataset by 7.5%:

  • size of input.osrm.mldgr changes from 6804054528 to 4580641280 bytes
  • dataset has two additional files input.osrm.end and input.osrm.enw with node durations and weights of size 422718464 bytes

/cc @TheMarex

Copy link
Member

@TheMarex TheMarex left a comment

Choose a reason for hiding this comment

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

Just some questions around the bit-fiddling we are doing and some nitpicks. Otherwise looks fine!

}
}

MultiLevelGraph(Vector<typename SuperT::NodeArrayEntry> node_array_,
Copy link
Member

Choose a reason for hiding this comment

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

Using some class-scope type aliases might be easier to read, like using NodeArrayEntry = typename SuperT::NodeArrayEntryT.

BOOST_ASSERT_MSG(edge_data.weight > 0, "edge_weight invalid");
const EdgeWeight to_weight = weight + edge_data.weight;
const auto node_weight =
facade.GetNodeWeight(DIRECTION == FORWARD_DIRECTION ? node : to);
Copy link
Member

Choose a reason for hiding this comment

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

Good catch, didn't think about the reverse-case here. 👍

@@ -146,6 +149,14 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
return max_border_node_id;
}

auto data() &&
Copy link
Member

Choose a reason for hiding this comment

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

This is a kind of weird mechanism. Do you think we could also solve this by protected access to these members by the sub-class? Or is this a problem with templates?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is not directly a problem with templates but with different EdgeBasedGraphEdgeData template arguments of customizer and partitioner graphs and customizer::MultiLevelGraph is not allowed to access protected members of partitioner::MultiLevelGraph.

An rvalue qualifier && is just a safety belt to prevent using an object instance after graph.data() call and explicit requirement for std::move(graph).data(). && here and std::move at the calling place can be removed.

return region.layout.GetBlockSize(name);
}

private:
const AllocatedRegion &GetBlockRegion(const std::string &name) const
Copy link
Member

Choose a reason for hiding this comment

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

Nice refactor, thanks! 👍

// Convert node weights for oneway streets to INVALID_EDGE_WEIGHT
for (auto &weight : node_weights)
{
weight = (weight & 0x80000000) ? INVALID_EDGE_WEIGHT : weight;
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 understand this part? We change the weight to INVALID_EDGE_WEIGHT if we MSB is set, but why not save it as INVALID_EDGE_WEIGHT in the first place?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the extractor where the value is computed it is not possible to say how node weights will be used later:

  • in contraction it must be INVALID_EDGE_WEIGHT to make loop edges at

    if (path_weight < node_weights[node])
    If node_weights[node] is not INVALID_EDGE_WEIGHT then path_weight of the loop edge will be always larger than the node weight value and the condition will be always false.

  • for MLD node_weights[node] must be a correct value otherwise GetNodeWeight will return INVALID_EDGE_WEIGHT that will break routing

The MSB flag is used to distinguish these usage scenarios.

Copy link
Member

Choose a reason for hiding this comment

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

Oh the problem is the reverse search of MLD? Okay yeah that is pretty ugly, but makes sense. I feel this deserves a better comment because this is a "hack".

auto graph = LoadAndUpdateEdgeExpandedGraph(
config, mlp, node_weights, node_durations, connectivity_checksum);
BOOST_ASSERT(graph.GetNumberOfNodes() == node_weights.size());
std::for_each(node_weights.begin(), node_weights.end(), [](auto &w) { w &= 0x7fffffff; });
Copy link
Member

Choose a reason for hiding this comment

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

Same here, why can't we enforce the MSB clipping where this data is generated?

if (nbe_to_ebn_mapping[edge_id_1] != SPECIAL_NODEID &&
nbe_to_ebn_mapping[edge_id_2] == SPECIAL_NODEID)
m_edge_based_node_weights[nbe_to_ebn_mapping[edge_id_1]] = INVALID_EDGE_WEIGHT;
m_edge_based_node_weights[nbe_to_ebn_mapping[edge_id_1]] |= 0x80000000;
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 get what setting the MSB vs. INVALID_EDGE_WEIGHT gives us here?

@TheMarex
Copy link
Member

@oxidase thanks for answering my questions. I think this might only need a better comment and then this is ready to merge.

@TheMarex TheMarex merged commit cacb162 into master Apr 28, 2018
@TheMarex TheMarex deleted the mld/node-weights branch April 28, 2018 06:59
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