Use Intel TBB's parallel_sort even for nested parallelism.
TBB has a global task scheduler (that's one of the reason TBB is not
linked statically but dyanmically instead). This allows control over all
running threads, enabling us to use nested parallelism and the scheduler
doing all the task allocation itself.
That is, nested parallel execution such as in
parallel_for(seq, [](const auto& rng){
parallel_sort(rng);
});
is no problem at all, as the scheduler still claims control over the
global environment.
Therefore, use `parallel_sort` Range overload where possible.
References:
- https://www.threadingbuildingblocks.org/docs/help/hh_goto.htm#reference/algorithms.htm
- https://www.threadingbuildingblocks.org/docs/help/hh_goto.htm#reference/algorithms/parallel_sort_func.htm
- https://www.threadingbuildingblocks.org/docs/help/hh_goto.htm#reference/task_scheduler.htm
- https://www.threadingbuildingblocks.org/docs/help/hh_goto.htm#reference/task_scheduler/task_scheduler_init_cls.htm
- https://www.threadingbuildingblocks.org/docs/help/hh_goto.htm#tbb_userguide/Initializing_and_Terminating_the_Library.htm
This commit is contained in:
+4
-1
@@ -28,9 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef CONTAINER_HPP
|
||||
#define CONTAINER_HPP
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -49,7 +52,7 @@ constexpr bool has_resize_method(...) noexcept { return false; }
|
||||
|
||||
template <typename Container> void sort_unique_resize(Container &vector) noexcept
|
||||
{
|
||||
std::sort(std::begin(vector), std::end(vector));
|
||||
tbb::parallel_sort(vector);
|
||||
const auto number_of_unique_elements =
|
||||
std::unique(std::begin(vector), std::end(vector)) - std::begin(vector);
|
||||
if (detail::has_resize_method(vector))
|
||||
|
||||
+16
-20
@@ -45,11 +45,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <unordered_map>
|
||||
#include <ios>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
@@ -57,8 +54,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* The since the restrictions reference nodes using their external node id,
|
||||
* we need to renumber it to the new internal id.
|
||||
*/
|
||||
unsigned loadRestrictionsFromFile(std::istream& input_stream,
|
||||
std::vector<TurnRestriction>& restriction_list)
|
||||
unsigned loadRestrictionsFromFile(std::istream &input_stream,
|
||||
std::vector<TurnRestriction> &restriction_list)
|
||||
{
|
||||
const FingerPrint fingerprint_valid = FingerPrint::GetValid();
|
||||
FingerPrint fingerprint_loaded;
|
||||
@@ -74,14 +71,13 @@ unsigned loadRestrictionsFromFile(std::istream& input_stream,
|
||||
restriction_list.resize(number_of_usable_restrictions);
|
||||
if (number_of_usable_restrictions > 0)
|
||||
{
|
||||
input_stream.read((char *) restriction_list.data(),
|
||||
number_of_usable_restrictions * sizeof(TurnRestriction));
|
||||
input_stream.read((char *)restriction_list.data(),
|
||||
number_of_usable_restrictions * sizeof(TurnRestriction));
|
||||
}
|
||||
|
||||
return number_of_usable_restrictions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads the beginning of an .osrm file and produces:
|
||||
* - list of barrier nodes
|
||||
@@ -132,36 +128,36 @@ NodeID loadNodesFromFile(std::istream &input_stream,
|
||||
/**
|
||||
* Reads a .osrm file and produces the edges.
|
||||
*/
|
||||
NodeID loadEdgesFromFile(std::istream &input_stream,
|
||||
std::vector<NodeBasedEdge> &edge_list)
|
||||
NodeID loadEdgesFromFile(std::istream &input_stream, std::vector<NodeBasedEdge> &edge_list)
|
||||
{
|
||||
EdgeID m;
|
||||
input_stream.read(reinterpret_cast<char *>(&m), sizeof(unsigned));
|
||||
edge_list.resize(m);
|
||||
SimpleLogger().Write() << " and " << m << " edges ";
|
||||
|
||||
input_stream.read((char *) edge_list.data(), m * sizeof(NodeBasedEdge));
|
||||
input_stream.read((char *)edge_list.data(), m * sizeof(NodeBasedEdge));
|
||||
|
||||
BOOST_ASSERT(edge_list.size() > 0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
SimpleLogger().Write() << "Validating loaded edges...";
|
||||
std::sort(edge_list.begin(), edge_list.end(),
|
||||
[](const NodeBasedEdge& lhs, const NodeBasedEdge& rhs)
|
||||
{
|
||||
return (lhs.source < rhs.source) || (lhs.source == rhs.source && lhs.target < rhs.target);
|
||||
});
|
||||
tbb::parallel_sort(edge_list, [](const NodeBasedEdge &lhs, const NodeBasedEdge &rhs)
|
||||
{
|
||||
return (lhs.source < rhs.source) ||
|
||||
(lhs.source == rhs.source && lhs.target < rhs.target);
|
||||
});
|
||||
for (auto i = 1u; i < edge_list.size(); ++i)
|
||||
{
|
||||
const auto& edge = edge_list[i];
|
||||
const auto& prev_edge = edge_list[i-1];
|
||||
const auto &edge = edge_list[i];
|
||||
const auto &prev_edge = edge_list[i - 1];
|
||||
|
||||
BOOST_ASSERT_MSG(edge.weight > 0, "loaded null weight");
|
||||
BOOST_ASSERT_MSG(edge.forward, "edge must be oriented in forward direction");
|
||||
BOOST_ASSERT_MSG(edge.travel_mode != TRAVEL_MODE_INACCESSIBLE, "loaded non-accessible");
|
||||
|
||||
BOOST_ASSERT_MSG(edge.source != edge.target, "loaded edges contain a loop");
|
||||
BOOST_ASSERT_MSG(edge.source != prev_edge.source || edge.target != prev_edge.target, "loaded edges contain a multi edge");
|
||||
BOOST_ASSERT_MSG(edge.source != prev_edge.source || edge.target != prev_edge.target,
|
||||
"loaded edges contain a multi edge");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user