Merge pull request #1028 from TheMarex/tbb-port

Port from OpenMP to TBB
This commit is contained in:
Dennis Luxen 2014-05-22 16:57:06 +02:00
commit 885dbe1e65
14 changed files with 586 additions and 222 deletions

View File

@ -7,7 +7,7 @@ install:
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test - sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
- sudo add-apt-repository -y ppa:boost-latest/ppa - sudo add-apt-repository -y ppa:boost-latest/ppa
- sudo apt-get update >/dev/null - sudo apt-get update >/dev/null
- sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems - sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems libtbb-dev
- sudo apt-get -q install g++-4.7 - sudo apt-get -q install g++-4.7
- sudo apt-get install libboost1.54-all-dev - sudo apt-get install libboost1.54-all-dev
#luabind #luabind

View File

@ -177,6 +177,11 @@ target_link_libraries(osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION COOR
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
find_package(TBB REQUIRED)
target_link_libraries(osrm-extract ${TBB_LIBRARIES})
target_link_libraries(osrm-prepare ${TBB_LIBRARIES})
include_directories(${TBB_INCLUDE_DIR})
find_package(Lua52) find_package(Lua52)
if(NOT LUA52_FOUND) if(NOT LUA52_FOUND)
find_package(Lua51 REQUIRED) find_package(Lua51 REQUIRED)

View File

@ -38,9 +38,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/OpenMPWrapper.h" #include "../Util/OpenMPWrapper.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h" #include "../Util/StringUtil.h"
#include "../Util/TimingUtil.h"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <tbb/enumerable_thread_specific.h>
#include <tbb/parallel_for.h>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <vector> #include <vector>
@ -125,6 +129,28 @@ class Contractor
bool is_independent : 1; bool is_independent : 1;
}; };
struct ThreadDataContainer
{
ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {}
inline ContractorThreadData* getThreadData()
{
bool exists = false;
auto& ref = data.local(exists);
if (!exists)
{
ref = std::make_shared<ContractorThreadData>(number_of_nodes);
}
return ref.get();
}
int number_of_nodes;
typedef tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>> EnumerableThreadData;
EnumerableThreadData data;
};
public: public:
template <class ContainerT> Contractor(int nodes, ContainerT &input_edge_list) template <class ContainerT> Contractor(int nodes, ContainerT &input_edge_list)
{ {
@ -262,39 +288,51 @@ class Contractor
void Run() void Run()
{ {
// for the preperation we can use a big grain size, which is much faster (probably cache)
constexpr size_t InitGrainSize = 100000;
constexpr size_t PQGrainSize = 100000;
// auto_partitioner will automatically increase the blocksize if we have
// a lot of data. It is *important* for the last loop iterations
// (which have a very small dataset) that it is devisible.
constexpr size_t IndependentGrainSize = 1;
constexpr size_t ContractGrainSize = 1;
constexpr size_t NeighboursGrainSize = 1;
constexpr size_t DeleteGrainSize = 1;
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes(); const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
Percent p(number_of_nodes); Percent p(number_of_nodes);
const unsigned thread_count = omp_get_max_threads(); ThreadDataContainer thread_data_list(number_of_nodes);
std::vector<ContractorThreadData *> thread_data_list;
for (unsigned thread_id = 0; thread_id < thread_count; ++thread_id)
{
thread_data_list.push_back(new ContractorThreadData(number_of_nodes));
}
std::cout << "Contractor is using " << thread_count << " threads" << std::endl;
NodeID number_of_contracted_nodes = 0; NodeID number_of_contracted_nodes = 0;
std::vector<RemainingNodeData> remaining_nodes(number_of_nodes); std::vector<RemainingNodeData> remaining_nodes(number_of_nodes);
std::vector<float> node_priorities(number_of_nodes); std::vector<float> node_priorities(number_of_nodes);
std::vector<NodePriorityData> node_data(number_of_nodes); std::vector<NodePriorityData> node_data(number_of_nodes);
// initialize priorities in parallel
#pragma omp parallel for schedule(guided) // initialize priorities in parallel
for (int x = 0; x < (int)number_of_nodes; ++x) tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
{ [&remaining_nodes](const tbb::blocked_range<int>& range)
remaining_nodes[x].id = x; {
} for (int x = range.begin(); x != range.end(); ++x)
{
remaining_nodes[x].id = x;
}
}
);
std::cout << "initializing elimination PQ ..." << std::flush; std::cout << "initializing elimination PQ ..." << std::flush;
#pragma omp parallel tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, PQGrainSize),
{ [this, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
#pragma omp parallel for schedule(guided)
for (int x = 0; x < (int)number_of_nodes; ++x)
{ {
node_priorities[x] = EvaluateNodePriority(data, &node_data[x], x); ContractorThreadData *data = thread_data_list.getThreadData();
for (int x = range.begin(); x != range.end(); ++x)
{
node_priorities[x] = this->EvaluateNodePriority(data, &node_data[x], x);
}
} }
} );
std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..." std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..."
<< std::flush; << std::flush;
@ -309,11 +347,7 @@ class Contractor
std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush; std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush;
// Delete old heap data to free memory that we need for the coming operations // Delete old heap data to free memory that we need for the coming operations
for (ContractorThreadData *data : thread_data_list) thread_data_list.data.clear();
{
delete data;
}
thread_data_list.clear();
// Create new priority array // Create new priority array
std::vector<float> new_node_priority(remaining_nodes.size()); std::vector<float> new_node_priority(remaining_nodes.size());
@ -396,61 +430,69 @@ class Contractor
// INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH! // INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
// reinitialize heaps and ThreadData objects with appropriate size // reinitialize heaps and ThreadData objects with appropriate size
for (unsigned thread_id = 0; thread_id < thread_count; ++thread_id) thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes();
{
thread_data_list.push_back(
new ContractorThreadData(contractor_graph->GetNumberOfNodes()));
}
} }
const int last = (int)remaining_nodes.size(); const int last = (int)remaining_nodes.size();
#pragma omp parallel tbb::parallel_for(tbb::blocked_range<int>(0, last, IndependentGrainSize),
{ [this, &node_priorities, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
// determine independent node set
ContractorThreadData *const data = thread_data_list[omp_get_thread_num()];
#pragma omp for schedule(guided)
for (int i = 0; i < last; ++i)
{ {
const NodeID node = remaining_nodes[i].id; ContractorThreadData *data = thread_data_list.getThreadData();
remaining_nodes[i].is_independent = // determine independent node set
IsNodeIndependent(node_priorities, data, node); for (int i = range.begin(); i != range.end(); ++i)
{
const NodeID node = remaining_nodes[i].id;
remaining_nodes[i].is_independent =
this->IsNodeIndependent(node_priorities, data, node);
}
} }
} );
const auto first = stable_partition(remaining_nodes.begin(), const auto first = stable_partition(remaining_nodes.begin(),
remaining_nodes.end(), remaining_nodes.end(),
[](RemainingNodeData node_data) [](RemainingNodeData node_data)
{ return !node_data.is_independent; }); { return !node_data.is_independent; });
const int first_independent_node = first - remaining_nodes.begin(); const int first_independent_node = first - remaining_nodes.begin();
// contract independent nodes
#pragma omp parallel
{
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
#pragma omp for schedule(guided) nowait
for (int position = first_independent_node; position < last; ++position)
{
NodeID x = remaining_nodes[position].id;
ContractNode<false>(data, x);
}
std::sort(data->inserted_edges.begin(), data->inserted_edges.end()); // contract independent nodes
} tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize),
#pragma omp parallel [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
{
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
#pragma omp for schedule(guided) nowait
for (int position = first_independent_node; position < last; ++position)
{ {
NodeID x = remaining_nodes[position].id; ContractorThreadData *data = thread_data_list.getThreadData();
DeleteIncomingEdges(data, x); for (int position = range.begin(); position != range.end(); ++position)
{
const NodeID x = remaining_nodes[position].id;
this->ContractNode<false>(data, x);
}
} }
} );
// insert new edges // make sure we really sort each block
for (unsigned thread_id = 0; thread_id < thread_count; ++thread_id) tbb::parallel_for(thread_data_list.data.range(),
{ [&](const ThreadDataContainer::EnumerableThreadData::range_type& range)
ContractorThreadData &data = *thread_data_list[thread_id];
for (const ContractorEdge &edge : data.inserted_edges)
{ {
auto current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target); for (auto& data : range)
std::sort(data->inserted_edges.begin(),
data->inserted_edges.end());
}
);
tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, DeleteGrainSize),
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position)
{
const NodeID x = remaining_nodes[position].id;
this->DeleteIncomingEdges(data, x);
}
}
);
// insert new edges
for (auto& data : thread_data_list.data)
{
for (const ContractorEdge &edge : data->inserted_edges)
{
const EdgeID current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target);
if (current_edge_ID < contractor_graph->EndEdges(edge.source)) if (current_edge_ID < contractor_graph->EndEdges(edge.source))
{ {
ContractorGraph::EdgeData &current_data = ContractorGraph::EdgeData &current_data =
@ -466,19 +508,21 @@ class Contractor
} }
contractor_graph->InsertEdge(edge.source, edge.target, edge.data); contractor_graph->InsertEdge(edge.source, edge.target, edge.data);
} }
data.inserted_edges.clear(); data->inserted_edges.clear();
} }
// update priorities
#pragma omp parallel tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize),
{ [this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
#pragma omp for schedule(guided) nowait
for (int position = first_independent_node; position < last; ++position)
{ {
NodeID x = remaining_nodes[position].id; ContractorThreadData *data = thread_data_list.getThreadData();
UpdateNodeNeighbours(node_priorities, node_data, data, x); for (int position = range.begin(); position != range.end(); ++position)
{
NodeID x = remaining_nodes[position].id;
this->UpdateNodeNeighbours(node_priorities, node_data, data, x);
}
} }
} );
// remove contracted nodes from the pool // remove contracted nodes from the pool
number_of_contracted_nodes += last - first_independent_node; number_of_contracted_nodes += last - first_independent_node;
remaining_nodes.resize(first_independent_node); remaining_nodes.resize(first_independent_node);
@ -510,11 +554,8 @@ class Contractor
p.printStatus(number_of_contracted_nodes); p.printStatus(number_of_contracted_nodes);
} }
for (ContractorThreadData *data : thread_data_list)
{ thread_data_list.data.clear();
delete data;
}
thread_data_list.clear();
} }
template <class Edge> inline void GetEdges(DeallocatingVector<Edge> &edges) template <class Edge> inline void GetEdges(DeallocatingVector<Edge> &edges)
@ -769,7 +810,6 @@ class Contractor
true, true,
true, true,
false); false);
;
inserted_edges.push_back(new_edge); inserted_edges.push_back(new_edge);
std::swap(new_edge.source, new_edge.target); std::swap(new_edge.source, new_edge.target);
new_edge.data.forward = false; new_edge.data.forward = false;

View File

@ -28,8 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "TemporaryStorage.h" #include "TemporaryStorage.h"
StreamData::StreamData() StreamData::StreamData()
: write_mode(true), temp_path(boost::filesystem::unique_path(temp_directory.append( : write_mode(true), temp_path(boost::filesystem::unique_path(temp_directory / TemporaryFilePattern)),
TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
temp_file(new boost::filesystem::fstream( temp_file(new boost::filesystem::fstream(
temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)), temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
readWriteMutex(std::make_shared<boost::mutex>()) readWriteMutex(std::make_shared<boost::mutex>())

View File

@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <vector> #include <vector>
#include <atomic>
template <typename EdgeDataT> class DynamicGraph template <typename EdgeDataT> class DynamicGraph
{ {
@ -198,7 +199,6 @@ template <typename EdgeDataT> class DynamicGraph
void DeleteEdge(const NodeIterator source, const EdgeIterator e) void DeleteEdge(const NodeIterator source, const EdgeIterator e)
{ {
Node &node = m_nodes[source]; Node &node = m_nodes[source];
#pragma omp atomic
--m_numEdges; --m_numEdges;
--node.edges; --node.edges;
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges); BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
@ -226,7 +226,6 @@ template <typename EdgeDataT> class DynamicGraph
} }
} }
#pragma omp atomic
m_numEdges -= deleted; m_numEdges -= deleted;
m_nodes[source].edges -= deleted; m_nodes[source].edges -= deleted;
@ -272,7 +271,7 @@ template <typename EdgeDataT> class DynamicGraph
}; };
NodeIterator m_numNodes; NodeIterator m_numNodes;
EdgeIterator m_numEdges; std::atomic_uint m_numEdges;
std::vector<Node> m_nodes; std::vector<Node> m_nodes;
DeallocatingVector<Edge> m_edges; DeallocatingVector<Edge> m_edges;

View File

@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/OpenMPWrapper.h" #include "../Util/OpenMPWrapper.h"
#include <iostream> #include <iostream>
#include <atomic>
class Percent class Percent
{ {
@ -61,20 +62,18 @@ class Percent
void printIncrement() void printIncrement()
{ {
#pragma omp atomic
++m_current_value; ++m_current_value;
printStatus(m_current_value); printStatus(m_current_value);
} }
void printAddition(const unsigned addition) void printAddition(const unsigned addition)
{ {
#pragma omp atomic
m_current_value += addition; m_current_value += addition;
printStatus(m_current_value); printStatus(m_current_value);
} }
private: private:
unsigned m_current_value; std::atomic_uint m_current_value;
unsigned m_max_value; unsigned m_max_value;
unsigned m_percent_interval; unsigned m_percent_interval;
unsigned m_next_threshold; unsigned m_next_threshold;

View File

@ -48,6 +48,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <tbb/parallel_for.h>
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <chrono> #include <chrono>
@ -278,24 +280,33 @@ class StaticRTree
HilbertCode get_hilbert_number; HilbertCode get_hilbert_number;
// generate auxiliary vector of hilbert-values // generate auxiliary vector of hilbert-values
#pragma omp parallel for schedule(guided) tbb::parallel_for(tbb::blocked_range<uint64_t>(0, m_element_count),
for (uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) [&input_data_vector,
{ &input_wrapper_vector,
input_wrapper_vector[element_counter].m_array_index = element_counter; &get_hilbert_number,
// Get Hilbert-Value for centroid in mercartor projection &coordinate_list](const tbb::blocked_range<uint64_t>& range)
DataT const &current_element = input_data_vector[element_counter]; {
FixedPointCoordinate current_centroid = for (uint64_t element_counter = range.begin(); element_counter != range.end(); ++element_counter)
DataT::Centroid(FixedPointCoordinate(coordinate_list.at(current_element.u).lat, {
coordinate_list.at(current_element.u).lon), WrappedInputElement &current_wrapper = input_wrapper_vector[element_counter];
FixedPointCoordinate(coordinate_list.at(current_element.v).lat, current_wrapper.m_array_index = element_counter;
coordinate_list.at(current_element.v).lon));
current_centroid.lat =
COORDINATE_PRECISION * lat2y(current_centroid.lat / COORDINATE_PRECISION);
uint64_t current_hilbert_value = get_hilbert_number(current_centroid); DataT const &current_element = input_data_vector[element_counter];
input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
} // Get Hilbert-Value for centroid in mercartor projection
FixedPointCoordinate current_centroid =
DataT::Centroid(FixedPointCoordinate(coordinate_list.at(current_element.u).lat,
coordinate_list.at(current_element.u).lon),
FixedPointCoordinate(coordinate_list.at(current_element.v).lat,
coordinate_list.at(current_element.v).lon));
current_centroid.lat =
COORDINATE_PRECISION * lat2y(current_centroid.lat / COORDINATE_PRECISION);
current_wrapper.m_hilbert_value = get_hilbert_number(current_centroid);
}
}
);
// open leaf file // open leaf file
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary); boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
@ -383,17 +394,22 @@ class StaticRTree
// reverse and renumber tree to have root at index 0 // reverse and renumber tree to have root at index 0
std::reverse(m_search_tree.begin(), m_search_tree.end()); std::reverse(m_search_tree.begin(), m_search_tree.end());
#pragma omp parallel for schedule(guided) uint32_t search_tree_size = m_search_tree.size();
for (uint32_t i = 0; i < m_search_tree.size(); ++i) tbb::parallel_for(tbb::blocked_range<uint32_t>(0, search_tree_size),
{ [this, &search_tree_size](const tbb::blocked_range<uint32_t>& range)
TreeNode &current_tree_node = m_search_tree[i];
for (uint32_t j = 0; j < current_tree_node.child_count; ++j)
{ {
const uint32_t old_id = current_tree_node.children[j]; for (uint32_t i = range.begin(); i != range.end(); ++i)
const uint32_t new_id = m_search_tree.size() - old_id - 1; {
current_tree_node.children[j] = new_id; TreeNode &current_tree_node = this->m_search_tree[i];
for (uint32_t j = 0; j < current_tree_node.child_count; ++j)
{
const uint32_t old_id = current_tree_node.children[j];
const uint32_t new_id = search_tree_size - old_id - 1;
current_tree_node.children[j] = new_id;
}
}
} }
} );
// open tree file // open tree file
boost::filesystem::ofstream tree_node_file(tree_node_filename, std::ios::binary); boost::filesystem::ofstream tree_node_file(tree_node_filename, std::ios::binary);

View File

@ -42,7 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks, BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks,
ScriptingEnvironment &scripting_environment) ScriptingEnvironment &scripting_environment)
: extractor_callbacks(extractor_callbacks), : extractor_callbacks(extractor_callbacks),
lua_state(scripting_environment.getLuaStateForThreadID(0)), lua_state(scripting_environment.getLuaState()),
scripting_environment(scripting_environment), use_turn_restrictions(true) scripting_environment(scripting_environment), use_turn_restrictions(true)
{ {
ReadUseRestrictionsSetting(); ReadUseRestrictionsSetting();

View File

@ -40,6 +40,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <tbb/parallel_for.h>
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include <zlib.h> #include <zlib.h>
@ -257,16 +259,18 @@ inline void PBFParser::parseDenseNode(ParserThreadData *thread_data)
denseTagIndex += 2; denseTagIndex += 2;
} }
} }
#pragma omp parallel
{ tbb::parallel_for(tbb::blocked_range<size_t>(0, extracted_nodes_vector.size()),
const int thread_num = omp_get_thread_num(); [this, &extracted_nodes_vector](const tbb::blocked_range<size_t>& range)
#pragma omp parallel for schedule(guided)
for (int i = 0; i < number_of_nodes; ++i)
{ {
ImportNode &import_node = extracted_nodes_vector[i]; lua_State* lua_state = this->scripting_environment.getLuaState();
ParseNodeInLua(import_node, scripting_environment.getLuaStateForThreadID(thread_num)); for (size_t i = range.begin(); i != range.end(); i++)
{
ImportNode &import_node = extracted_nodes_vector[i];
ParseNodeInLua(import_node, lua_state);
}
} }
} );
for (const ImportNode &import_node : extracted_nodes_vector) for (const ImportNode &import_node : extracted_nodes_vector)
{ {
@ -424,16 +428,21 @@ inline void PBFParser::parseWay(ParserThreadData *thread_data)
} }
} }
#pragma omp parallel for schedule(guided) // TODO: investigate if schedule guided will be handled by tbb automatically
for (int i = 0; i < number_of_ways; ++i) tbb::parallel_for(tbb::blocked_range<size_t>(0, parsed_way_vector.size()),
{ [this, &parsed_way_vector](const tbb::blocked_range<size_t>& range)
ExtractionWay &extraction_way = parsed_way_vector[i];
if (2 <= extraction_way.path.size())
{ {
ParseWayInLua(extraction_way, lua_State* lua_state = this->scripting_environment.getLuaState();
scripting_environment.getLuaStateForThreadID(omp_get_thread_num())); for (size_t i = range.begin(); i != range.end(); i++)
{
ExtractionWay &extraction_way = parsed_way_vector[i];
if (2 <= extraction_way.path.size())
{
ParseWayInLua(extraction_way, lua_state);
}
}
} }
} );
for (ExtractionWay &extraction_way : parsed_way_vector) for (ExtractionWay &extraction_way : parsed_way_vector)
{ {

View File

@ -38,87 +38,85 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ScriptingEnvironment::ScriptingEnvironment() {} ScriptingEnvironment::ScriptingEnvironment() {}
ScriptingEnvironment::ScriptingEnvironment(const char *file_name) ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
: file_name(file_name)
{ {
SimpleLogger().Write() << "Using script " << file_name; SimpleLogger().Write() << "Using script " << file_name;
// Create a new lua state
for (int i = 0; i < omp_get_max_threads(); ++i)
{
lua_state_vector.push_back(luaL_newstate());
}
// Connect LuaBind to this lua state for all threads
#pragma omp parallel
{
lua_State *lua_state = getLuaStateForThreadID(omp_get_thread_num());
luabind::open(lua_state);
// open utility libraries string library;
luaL_openlibs(lua_state);
luaAddScriptFolderToLoadPath(lua_state, file_name);
// Add our function to the state's global scope
luabind::module(lua_state)[
luabind::def("print", LUA_print<std::string>),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration)
];
luabind::module(lua_state)[luabind::class_<HashTable<std::string, std::string>>("keyVals")
.def("Add", &HashTable<std::string, std::string>::Add)
.def("Find", &HashTable<std::string, std::string>::Find)
.def("Holds", &HashTable<std::string, std::string>::Holds)];
luabind::module(lua_state)[luabind::class_<ImportNode>("Node")
.def(luabind::constructor<>())
.def_readwrite("lat", &ImportNode::lat)
.def_readwrite("lon", &ImportNode::lon)
.def_readonly("id", &ImportNode::id)
.def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("tags", &ImportNode::keyVals)];
luabind::module(lua_state)
[luabind::class_<ExtractionWay>("Way")
.def(luabind::constructor<>())
.def_readonly("id", &ExtractionWay::id)
.def_readwrite("name", &ExtractionWay::name)
.def_readwrite("speed", &ExtractionWay::speed)
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
.def_readwrite("duration", &ExtractionWay::duration)
.def_readwrite("type", &ExtractionWay::type)
.def_readwrite("access", &ExtractionWay::access)
.def_readwrite("roundabout", &ExtractionWay::roundabout)
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
.def_readwrite("tags", &ExtractionWay::keyVals)
.def_readwrite("direction", &ExtractionWay::direction)
.enum_("constants")[
luabind::value("notSure", 0),
luabind::value("oneway", 1),
luabind::value("bidirectional", 2),
luabind::value("opposite", 3)
]];
// fails on c++11/OS X 10.9
luabind::module(lua_state)[luabind::class_<std::vector<std::string>>("vector").def(
"Add",
static_cast<void (std::vector<std::string>::*)(const std::string &)>(
&std::vector<std::string>::push_back))];
if (0 != luaL_dofile(lua_state, file_name))
{
throw OSRMException("ERROR occured in scripting block");
}
}
} }
ScriptingEnvironment::~ScriptingEnvironment() void ScriptingEnvironment::initLuaState(lua_State* lua_state)
{ {
for (unsigned i = 0; i < lua_state_vector.size(); ++i) luabind::open(lua_state);
// open utility libraries string library;
luaL_openlibs(lua_state);
luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
// Add our function to the state's global scope
luabind::module(lua_state)[
luabind::def("print", LUA_print<std::string>),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration)
];
luabind::module(lua_state)[luabind::class_<HashTable<std::string, std::string>>("keyVals")
.def("Add", &HashTable<std::string, std::string>::Add)
.def("Find", &HashTable<std::string, std::string>::Find)
.def("Holds", &HashTable<std::string, std::string>::Holds)];
luabind::module(lua_state)[luabind::class_<ImportNode>("Node")
.def(luabind::constructor<>())
.def_readwrite("lat", &ImportNode::lat)
.def_readwrite("lon", &ImportNode::lon)
.def_readonly("id", &ImportNode::id)
.def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("tags", &ImportNode::keyVals)];
luabind::module(lua_state)
[luabind::class_<ExtractionWay>("Way")
.def(luabind::constructor<>())
.def_readonly("id", &ExtractionWay::id)
.def_readwrite("name", &ExtractionWay::name)
.def_readwrite("speed", &ExtractionWay::speed)
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
.def_readwrite("duration", &ExtractionWay::duration)
.def_readwrite("type", &ExtractionWay::type)
.def_readwrite("access", &ExtractionWay::access)
.def_readwrite("roundabout", &ExtractionWay::roundabout)
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
.def_readwrite("tags", &ExtractionWay::keyVals)
.def_readwrite("direction", &ExtractionWay::direction)
.enum_("constants")[
luabind::value("notSure", 0),
luabind::value("oneway", 1),
luabind::value("bidirectional", 2),
luabind::value("opposite", 3)
]];
// fails on c++11/OS X 10.9
luabind::module(lua_state)[luabind::class_<std::vector<std::string>>("vector").def(
"Add",
static_cast<void (std::vector<std::string>::*)(const std::string &)>(
&std::vector<std::string>::push_back))];
if (0 != luaL_dofile(lua_state, file_name.c_str()))
{ {
// lua_state_vector[i]; throw OSRMException("ERROR occured in scripting block");
} }
} }
lua_State *ScriptingEnvironment::getLuaStateForThreadID(const int id) { return lua_state_vector[id]; } lua_State *ScriptingEnvironment::getLuaState()
{
bool initialized = false;
auto& ref = script_contexts.local(initialized);
if (!initialized)
{
std::shared_ptr<lua_State> state(luaL_newstate(), lua_close);
ref = state;
initLuaState(ref.get());
}
return ref.get();
}

View File

@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SCRIPTINGENVIRONMENT_H_ #ifndef SCRIPTINGENVIRONMENT_H_
#define SCRIPTINGENVIRONMENT_H_ #define SCRIPTINGENVIRONMENT_H_
#include <vector> #include <string>
#include <memory>
#include <tbb/enumerable_thread_specific.h>
struct lua_State; struct lua_State;
@ -37,11 +39,14 @@ class ScriptingEnvironment
public: public:
ScriptingEnvironment(); ScriptingEnvironment();
explicit ScriptingEnvironment(const char *file_name); explicit ScriptingEnvironment(const char *file_name);
virtual ~ScriptingEnvironment();
lua_State *getLuaStateForThreadID(const int); lua_State *getLuaState();
std::vector<lua_State *> lua_state_vector; private:
void initLuaState(lua_State* lua_state);
std::string file_name;
tbb::enumerable_thread_specific<std::shared_ptr<lua_State>> script_contexts;
}; };
#endif /* SCRIPTINGENVIRONMENT_H_ */ #endif /* SCRIPTINGENVIRONMENT_H_ */

283
cmake/FindTBB.cmake Normal file
View File

@ -0,0 +1,283 @@
# Locate Intel Threading Building Blocks include paths and libraries
# FindTBB.cmake can be found at https://code.google.com/p/findtbb/
# Written by Hannes Hofmann <hannes.hofmann _at_ informatik.uni-erlangen.de>
# Improvements by Gino van den Bergen <gino _at_ dtecta.com>,
# Florian Uhlig <F.Uhlig _at_ gsi.de>,
# Jiri Marsik <jiri.marsik89 _at_ gmail.com>
# The MIT License
#
# Copyright (c) 2011 Hannes Hofmann
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# GvdB: This module uses the environment variable TBB_ARCH_PLATFORM which defines architecture and compiler.
# e.g. "ia32/vc8" or "em64t/cc4.1.0_libc2.4_kernel2.6.16.21"
# TBB_ARCH_PLATFORM is set by the build script tbbvars[.bat|.sh|.csh], which can be found
# in the TBB installation directory (TBB_INSTALL_DIR).
#
# GvdB: Mac OS X distribution places libraries directly in lib directory.
#
# For backwards compatibility, you may explicitely set the CMake variables TBB_ARCHITECTURE and TBB_COMPILER.
# TBB_ARCHITECTURE [ ia32 | em64t | itanium ]
# which architecture to use
# TBB_COMPILER e.g. vc9 or cc3.2.3_libc2.3.2_kernel2.4.21 or cc4.0.1_os10.4.9
# which compiler to use (detected automatically on Windows)
# This module respects
# TBB_INSTALL_DIR or $ENV{TBB21_INSTALL_DIR} or $ENV{TBB_INSTALL_DIR}
# This module defines
# TBB_INCLUDE_DIRS, where to find task_scheduler_init.h, etc.
# TBB_LIBRARY_DIRS, where to find libtbb, libtbbmalloc
# TBB_DEBUG_LIBRARY_DIRS, where to find libtbb_debug, libtbbmalloc_debug
# TBB_INSTALL_DIR, the base TBB install directory
# TBB_LIBRARIES, the libraries to link against to use TBB.
# TBB_DEBUG_LIBRARIES, the libraries to link against to use TBB with debug symbols.
# TBB_FOUND, If false, don't try to use TBB.
# TBB_INTERFACE_VERSION, as defined in tbb/tbb_stddef.h
if (WIN32)
# has em64t/vc8 em64t/vc9
# has ia32/vc7.1 ia32/vc8 ia32/vc9
set(_TBB_DEFAULT_INSTALL_DIR "C:/Program Files/Intel/TBB" "C:/Program Files (x86)/Intel/TBB")
set(_TBB_LIB_NAME "tbb")
set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
if (MSVC71)
set (_TBB_COMPILER "vc7.1")
endif(MSVC71)
if (MSVC80)
set(_TBB_COMPILER "vc8")
endif(MSVC80)
if (MSVC90)
set(_TBB_COMPILER "vc9")
endif(MSVC90)
if(MSVC10)
set(_TBB_COMPILER "vc10")
endif(MSVC10)
# Todo: add other Windows compilers such as ICL.
set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
endif (WIN32)
if (UNIX)
if (APPLE)
# MAC
set(_TBB_DEFAULT_INSTALL_DIR "/Library/Frameworks/Intel_TBB.framework/Versions")
# libs: libtbb.dylib, libtbbmalloc.dylib, *_debug
set(_TBB_LIB_NAME "tbb")
set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
# default flavor on apple: ia32/cc4.0.1_os10.4.9
# Jiri: There is no reason to presume there is only one flavor and
# that user's setting of variables should be ignored.
if(NOT TBB_COMPILER)
set(_TBB_COMPILER "cc4.0.1_os10.4.9")
elseif (NOT TBB_COMPILER)
set(_TBB_COMPILER ${TBB_COMPILER})
endif(NOT TBB_COMPILER)
if(NOT TBB_ARCHITECTURE)
set(_TBB_ARCHITECTURE "ia32")
elseif(NOT TBB_ARCHITECTURE)
set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
endif(NOT TBB_ARCHITECTURE)
else (APPLE)
# LINUX
set(_TBB_DEFAULT_INSTALL_DIR "/opt/intel/tbb" "/usr/local/include" "/usr/include")
set(_TBB_LIB_NAME "tbb")
set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
# has em64t/cc3.2.3_libc2.3.2_kernel2.4.21 em64t/cc3.3.3_libc2.3.3_kernel2.6.5 em64t/cc3.4.3_libc2.3.4_kernel2.6.9 em64t/cc4.1.0_libc2.4_kernel2.6.16.21
# has ia32/*
# has itanium/*
set(_TBB_COMPILER ${TBB_COMPILER})
set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
endif (APPLE)
endif (UNIX)
if (CMAKE_SYSTEM MATCHES "SunOS.*")
# SUN
# not yet supported
# has em64t/cc3.4.3_kernel5.10
# has ia32/*
endif (CMAKE_SYSTEM MATCHES "SunOS.*")
#-- Clear the public variables
set (TBB_FOUND "NO")
#-- Find TBB install dir and set ${_TBB_INSTALL_DIR} and cached ${TBB_INSTALL_DIR}
# first: use CMake variable TBB_INSTALL_DIR
if (TBB_INSTALL_DIR)
set (_TBB_INSTALL_DIR ${TBB_INSTALL_DIR})
endif (TBB_INSTALL_DIR)
# second: use environment variable
if (NOT _TBB_INSTALL_DIR)
if (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "")
set (_TBB_INSTALL_DIR $ENV{TBB_INSTALL_DIR})
endif (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "")
# Intel recommends setting TBB21_INSTALL_DIR
if (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "")
set (_TBB_INSTALL_DIR $ENV{TBB21_INSTALL_DIR})
endif (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "")
if (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "")
set (_TBB_INSTALL_DIR $ENV{TBB22_INSTALL_DIR})
endif (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "")
if (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "")
set (_TBB_INSTALL_DIR $ENV{TBB30_INSTALL_DIR})
endif (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "")
endif (NOT _TBB_INSTALL_DIR)
# third: try to find path automatically
if (NOT _TBB_INSTALL_DIR)
if (_TBB_DEFAULT_INSTALL_DIR)
set (_TBB_INSTALL_DIR ${_TBB_DEFAULT_INSTALL_DIR})
endif (_TBB_DEFAULT_INSTALL_DIR)
endif (NOT _TBB_INSTALL_DIR)
# sanity check
if (NOT _TBB_INSTALL_DIR)
message ("ERROR: Unable to find Intel TBB install directory. ${_TBB_INSTALL_DIR}")
else (NOT _TBB_INSTALL_DIR)
# finally: set the cached CMake variable TBB_INSTALL_DIR
if (NOT TBB_INSTALL_DIR)
set (TBB_INSTALL_DIR ${_TBB_INSTALL_DIR} CACHE PATH "Intel TBB install directory")
mark_as_advanced(TBB_INSTALL_DIR)
endif (NOT TBB_INSTALL_DIR)
#-- A macro to rewrite the paths of the library. This is necessary, because
# find_library() always found the em64t/vc9 version of the TBB libs
macro(TBB_CORRECT_LIB_DIR var_name)
# if (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t")
string(REPLACE em64t "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}})
# endif (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t")
string(REPLACE ia32 "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}})
string(REPLACE vc7.1 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
string(REPLACE vc8 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
string(REPLACE vc9 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
string(REPLACE vc10 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
endmacro(TBB_CORRECT_LIB_DIR var_content)
#-- Look for include directory and set ${TBB_INCLUDE_DIR}
set (TBB_INC_SEARCH_DIR ${_TBB_INSTALL_DIR}/include)
# Jiri: tbbvars now sets the CPATH environment variable to the directory
# containing the headers.
find_path(TBB_INCLUDE_DIR
tbb/task_scheduler_init.h
PATHS ${TBB_INC_SEARCH_DIR} ENV CPATH
)
mark_as_advanced(TBB_INCLUDE_DIR)
#-- Look for libraries
# GvdB: $ENV{TBB_ARCH_PLATFORM} is set by the build script tbbvars[.bat|.sh|.csh]
if (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
set (_TBB_LIBRARY_DIR
${_TBB_INSTALL_DIR}/lib/$ENV{TBB_ARCH_PLATFORM}
${_TBB_INSTALL_DIR}/$ENV{TBB_ARCH_PLATFORM}/lib
)
endif (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
# Jiri: This block isn't mutually exclusive with the previous one
# (hence no else), instead I test if the user really specified
# the variables in question.
if ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL ""))
# HH: deprecated
message(STATUS "[Warning] FindTBB.cmake: The use of TBB_ARCHITECTURE and TBB_COMPILER is deprecated and may not be supported in future versions. Please set \$ENV{TBB_ARCH_PLATFORM} (using tbbvars.[bat|csh|sh]).")
# Jiri: It doesn't hurt to look in more places, so I store the hints from
# ENV{TBB_ARCH_PLATFORM} and the TBB_ARCHITECTURE and TBB_COMPILER
# variables and search them both.
set (_TBB_LIBRARY_DIR "${_TBB_INSTALL_DIR}/${_TBB_ARCHITECTURE}/${_TBB_COMPILER}/lib" ${_TBB_LIBRARY_DIR})
endif ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL ""))
# GvdB: Mac OS X distribution places libraries directly in lib directory.
list(APPEND _TBB_LIBRARY_DIR ${_TBB_INSTALL_DIR}/lib)
# Jiri: No reason not to check the default paths. From recent versions,
# tbbvars has started exporting the LIBRARY_PATH and LD_LIBRARY_PATH
# variables, which now point to the directories of the lib files.
# It all makes more sense to use the ${_TBB_LIBRARY_DIR} as a HINTS
# argument instead of the implicit PATHS as it isn't hard-coded
# but computed by system introspection. Searching the LIBRARY_PATH
# and LD_LIBRARY_PATH environment variables is now even more important
# that tbbvars doesn't export TBB_ARCH_PLATFORM and it facilitates
# the use of TBB built from sources.
find_library(TBB_LIBRARY ${_TBB_LIB_NAME} HINTS ${_TBB_LIBRARY_DIR}
PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
find_library(TBB_MALLOC_LIBRARY ${_TBB_LIB_MALLOC_NAME} HINTS ${_TBB_LIBRARY_DIR}
PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
#Extract path from TBB_LIBRARY name
get_filename_component(TBB_LIBRARY_DIR ${TBB_LIBRARY} PATH)
#TBB_CORRECT_LIB_DIR(TBB_LIBRARY)
#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY)
mark_as_advanced(TBB_LIBRARY TBB_MALLOC_LIBRARY)
#-- Look for debug libraries
# Jiri: Changed the same way as for the release libraries.
find_library(TBB_LIBRARY_DEBUG ${_TBB_LIB_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
find_library(TBB_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_MALLOC_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
# Jiri: Self-built TBB stores the debug libraries in a separate directory.
# Extract path from TBB_LIBRARY_DEBUG name
get_filename_component(TBB_LIBRARY_DEBUG_DIR ${TBB_LIBRARY_DEBUG} PATH)
#TBB_CORRECT_LIB_DIR(TBB_LIBRARY_DEBUG)
#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY_DEBUG)
mark_as_advanced(TBB_LIBRARY_DEBUG TBB_MALLOC_LIBRARY_DEBUG)
if (TBB_INCLUDE_DIR)
if (TBB_LIBRARY)
set (TBB_FOUND "YES")
set (TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY} ${TBB_LIBRARIES})
set (TBB_DEBUG_LIBRARIES ${TBB_LIBRARY_DEBUG} ${TBB_MALLOC_LIBRARY_DEBUG} ${TBB_DEBUG_LIBRARIES})
set (TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR} CACHE PATH "TBB include directory" FORCE)
set (TBB_LIBRARY_DIRS ${TBB_LIBRARY_DIR} CACHE PATH "TBB library directory" FORCE)
# Jiri: Self-built TBB stores the debug libraries in a separate directory.
set (TBB_DEBUG_LIBRARY_DIRS ${TBB_LIBRARY_DEBUG_DIR} CACHE PATH "TBB debug library directory" FORCE)
mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARY_DIRS TBB_DEBUG_LIBRARY_DIRS TBB_LIBRARIES TBB_DEBUG_LIBRARIES)
message(STATUS "Found Intel TBB")
endif (TBB_LIBRARY)
endif (TBB_INCLUDE_DIR)
if (NOT TBB_FOUND)
message("ERROR: Intel TBB NOT found!")
message(STATUS "Looked for Threading Building Blocks in ${_TBB_INSTALL_DIR}")
# do only throw fatal, if this pkg is REQUIRED
if (TBB_FIND_REQUIRED)
message(FATAL_ERROR "Could NOT find TBB library.")
endif (TBB_FIND_REQUIRED)
endif (NOT TBB_FOUND)
endif (NOT _TBB_INSTALL_DIR)
if (TBB_FOUND)
set(TBB_INTERFACE_VERSION 0)
FILE(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _TBB_VERSION_CONTENTS)
STRING(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}")
set(TBB_INTERFACE_VERSION "${TBB_INTERFACE_VERSION}")
endif (TBB_FOUND)

View File

@ -42,12 +42,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstdlib> #include <cstdlib>
#include <thread>
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <tbb/task_scheduler_init.h>
ExtractorCallbacks *extractor_callbacks; ExtractorCallbacks *extractor_callbacks;
UUID uuid; UUID uuid;
@ -60,7 +63,7 @@ int main(int argc, char *argv[])
std::chrono::steady_clock::now(); std::chrono::steady_clock::now();
boost::filesystem::path config_file_path, input_path, profile_path; boost::filesystem::path config_file_path, input_path, profile_path;
int requested_num_threads; unsigned int requested_num_threads;
// declare a group of options that will be allowed only on command line // declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options"); boost::program_options::options_description generic_options("Options");
@ -78,7 +81,7 @@ int main(int argc, char *argv[])
&profile_path)->default_value("profile.lua"), &profile_path)->default_value("profile.lua"),
"Path to LUA routing profile")( "Path to LUA routing profile")(
"threads,t", "threads,t",
boost::program_options::value<int>(&requested_num_threads)->default_value(8), boost::program_options::value<unsigned int>(&requested_num_threads)->default_value(8),
"Number of threads to use"); "Number of threads to use");
// hidden options, will be allowed both on command line and in config file, but will not be // hidden options, will be allowed both on command line and in config file, but will not be
@ -163,18 +166,19 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
int real_num_threads = std::min(omp_get_num_procs(), requested_num_threads); unsigned int hardware_threads = std::max((unsigned int) 1, std::thread::hardware_concurrency());
unsigned int real_num_threads = std::min(hardware_threads, requested_num_threads);
SimpleLogger().Write() << "Input file: " << input_path.filename().string(); SimpleLogger().Write() << "Input file: " << input_path.filename().string();
SimpleLogger().Write() << "Profile: " << profile_path.filename().string(); SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
SimpleLogger().Write() << "Threads: " << real_num_threads << " (requested " SimpleLogger().Write() << "Threads: " << real_num_threads << " (requested "
<< requested_num_threads << ")"; << requested_num_threads << ")";
tbb::task_scheduler_init init(real_num_threads);
/*** Setup Scripting Environment ***/ /*** Setup Scripting Environment ***/
ScriptingEnvironment scripting_environment(profile_path.c_str()); ScriptingEnvironment scripting_environment(profile_path.c_str());
omp_set_num_threads(real_num_threads);
bool file_has_pbf_format(false); bool file_has_pbf_format(false);
std::string output_file_name = input_path.string(); std::string output_file_name = input_path.string();
std::string restriction_fileName = input_path.string(); std::string restriction_fileName = input_path.string();

View File

@ -49,11 +49,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <luabind/luabind.hpp> #include <luabind/luabind.hpp>
#include <thread>
#include <chrono> #include <chrono>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include <tbb/task_scheduler_init.h>
typedef QueryEdge::EdgeData EdgeData; typedef QueryEdge::EdgeData EdgeData;
typedef DynamicGraph<EdgeData>::InputEdge InputEdge; typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
typedef StaticGraph<EdgeData>::InputEdge StaticEdge; typedef StaticGraph<EdgeData>::InputEdge StaticEdge;
@ -66,6 +69,8 @@ std::vector<ImportEdge> edge_list;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
try try
{ {
LogPolicy::GetInstance().Unmute(); LogPolicy::GetInstance().Unmute();
@ -73,7 +78,7 @@ int main(int argc, char *argv[])
std::chrono::steady_clock::now(); std::chrono::steady_clock::now();
boost::filesystem::path config_file_path, input_path, restrictions_path, profile_path; boost::filesystem::path config_file_path, input_path, restrictions_path, profile_path;
int requested_num_threads; unsigned int requested_num_threads;
// declare a group of options that will be allowed only on command line // declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options"); boost::program_options::options_description generic_options("Options");
@ -95,7 +100,7 @@ int main(int argc, char *argv[])
->default_value("profile.lua"), ->default_value("profile.lua"),
"Path to LUA routing profile")( "Path to LUA routing profile")(
"threads,t", "threads,t",
boost::program_options::value<int>(&requested_num_threads)->default_value(8), boost::program_options::value<unsigned int>(&requested_num_threads)->default_value(8),
"Number of threads to use"); "Number of threads to use");
// hidden options, will be allowed both on command line and in config file, but will not be // hidden options, will be allowed both on command line and in config file, but will not be
@ -174,7 +179,8 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
int real_num_threads = std::min(omp_get_num_procs(), requested_num_threads); unsigned int hardware_threads = std::max((unsigned int) 1, std::thread::hardware_concurrency());
unsigned int real_num_threads = std::min(hardware_threads, requested_num_threads);
SimpleLogger().Write() << "Input file: " << input_path.filename().string(); SimpleLogger().Write() << "Input file: " << input_path.filename().string();
SimpleLogger().Write() << "Restrictions file: " << restrictions_path.filename().string(); SimpleLogger().Write() << "Restrictions file: " << restrictions_path.filename().string();
@ -182,7 +188,8 @@ int main(int argc, char *argv[])
SimpleLogger().Write() << "Threads: " << real_num_threads << " (requested " SimpleLogger().Write() << "Threads: " << real_num_threads << " (requested "
<< requested_num_threads << ")"; << requested_num_threads << ")";
omp_set_num_threads(real_num_threads); tbb::task_scheduler_init init(real_num_threads);
LogPolicy::GetInstance().Unmute(); LogPolicy::GetInstance().Unmute();
boost::filesystem::ifstream restriction_stream(restrictions_path, std::ios::binary); boost::filesystem::ifstream restriction_stream(restrictions_path, std::ios::binary);
TurnRestriction restriction; TurnRestriction restriction;