Merge pull request #275 from DennisOSRM/develop/hashBias
Develop/hash bias
This commit is contained in:
commit
1b52f67e5d
@ -31,14 +31,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
||||
#include "../DataStructures/BinaryHeap.h"
|
||||
#include "../DataStructures/DeallocatingVector.h"
|
||||
#include "../DataStructures/DynamicGraph.h"
|
||||
#include "../DataStructures/Percent.h"
|
||||
#include "../DataStructures/BinaryHeap.h"
|
||||
#include "../DataStructures/XORFastHash.h"
|
||||
#include "../Util/OpenMPReplacement.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
|
||||
class Contractor {
|
||||
|
||||
private:
|
||||
@ -77,8 +77,7 @@ private:
|
||||
|
||||
struct _PriorityData {
|
||||
int depth;
|
||||
NodeID bias;
|
||||
_PriorityData() : depth(0), bias(0) { }
|
||||
_PriorityData() : depth(0) { }
|
||||
};
|
||||
|
||||
struct _ContractionInformation {
|
||||
@ -99,13 +98,18 @@ public:
|
||||
|
||||
template<class ContainerT >
|
||||
Contractor( int nodes, ContainerT& inputEdges) {
|
||||
std::vector< _ContractorEdge > edges;
|
||||
edges.reserve( 2 * inputEdges.size() );
|
||||
BOOST_FOREACH(typename ContainerT::value_type & currentEdge, inputEdges) {
|
||||
DeallocatingVector< _ContractorEdge > edges;
|
||||
|
||||
typename ContainerT::deallocation_iterator diter = inputEdges.dbegin();
|
||||
typename ContainerT::deallocation_iterator dend = inputEdges.dend();
|
||||
|
||||
|
||||
//BOOST_FOREACH(typename ContainerT::value_type & currentEdge, inputEdges) {
|
||||
for(; diter!=dend; ++diter) {
|
||||
_ContractorEdge edge;
|
||||
edge.source = currentEdge.source();
|
||||
edge.target = currentEdge.target();
|
||||
edge.data = _ContractorEdgeData( (std::max)((int)currentEdge.weight(), 1 ), 1, currentEdge.id()/*, currentEdge.getNameIDOfTurnTarget(), currentEdge.turnInstruction()*/, false, currentEdge.isForward(), currentEdge.isBackward());
|
||||
edge.source = diter->source();
|
||||
edge.target = diter->target();
|
||||
edge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id()/*, currentEdge.getNameIDOfTurnTarget(), currentEdge.turnInstruction()*/, false, diter->isForward(), diter->isBackward());
|
||||
|
||||
assert( edge.data.distance > 0 );
|
||||
#ifndef NDEBUG
|
||||
@ -116,12 +120,12 @@ public:
|
||||
#endif
|
||||
edges.push_back( edge );
|
||||
std::swap( edge.source, edge.target );
|
||||
edge.data.forward = currentEdge.isBackward();
|
||||
edge.data.backward = currentEdge.isForward();
|
||||
edge.data.forward = diter->isBackward();
|
||||
edge.data.backward = diter->isForward();
|
||||
edges.push_back( edge );
|
||||
}
|
||||
//clear input vector and trim the current set of edges with the well-known swap trick
|
||||
ContainerT().swap( inputEdges );
|
||||
inputEdges.clear();
|
||||
|
||||
sort( edges.begin(), edges.end() );
|
||||
NodeID edge = 0;
|
||||
@ -169,7 +173,7 @@ public:
|
||||
}
|
||||
}
|
||||
std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl;
|
||||
edges.resize( edge );
|
||||
// edges.resize( edge );
|
||||
|
||||
_graph.reset( new _DynamicGraph( nodes, edges ) );
|
||||
edges.clear();
|
||||
@ -213,16 +217,13 @@ public:
|
||||
|
||||
NodeID numberOfContractedNodes = 0;
|
||||
std::vector< std::pair< NodeID, bool > > remainingNodes( numberOfNodes );
|
||||
std::vector< double > nodePriority( numberOfNodes );
|
||||
std::vector< float > nodePriority( numberOfNodes );
|
||||
std::vector< _PriorityData > nodeData( numberOfNodes );
|
||||
|
||||
//initialize the variables
|
||||
#pragma omp parallel for schedule ( guided )
|
||||
for ( int x = 0; x < ( int ) numberOfNodes; ++x )
|
||||
remainingNodes[x].first = x;
|
||||
std::random_shuffle( remainingNodes.begin(), remainingNodes.end() );
|
||||
for ( int x = 0; x < ( int ) numberOfNodes; ++x )
|
||||
nodeData[remainingNodes[x].first].bias = x;
|
||||
|
||||
std::cout << "initializing elimination PQ ..." << std::flush;
|
||||
#pragma omp parallel
|
||||
@ -238,7 +239,7 @@ public:
|
||||
bool flushedContractor = false;
|
||||
while ( numberOfContractedNodes < numberOfNodes ) {
|
||||
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){
|
||||
std::vector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
|
||||
DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
|
||||
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
|
||||
|
||||
//Delete old heap data to free memory that we need for the coming operations
|
||||
@ -249,7 +250,7 @@ public:
|
||||
|
||||
|
||||
//Create new priority array
|
||||
std::vector<double> newNodePriority(remainingNodes.size());
|
||||
std::vector<float> newNodePriority(remainingNodes.size());
|
||||
//this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction
|
||||
oldNodeIDFromNewNodeIDMap.resize(remainingNodes.size());
|
||||
//this map gives the new IDs from the old ones, necessary to remap targets from the remaining graph
|
||||
@ -309,7 +310,7 @@ public:
|
||||
//Replace old priorities array by new one
|
||||
nodePriority.swap(newNodePriority);
|
||||
//Delete old nodePriority vector
|
||||
std::vector<double>().swap(newNodePriority);
|
||||
std::vector<float>().swap(newNodePriority);
|
||||
//old Graph is removed
|
||||
_graph.reset();
|
||||
|
||||
@ -318,6 +319,7 @@ public:
|
||||
|
||||
//int nodes, const ContainerT &graph
|
||||
_graph.reset( new _DynamicGraph(remainingNodes.size(), newSetOfEdges));
|
||||
newSetOfEdges.clear();
|
||||
flushedContractor = true;
|
||||
|
||||
//INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
|
||||
@ -325,7 +327,6 @@ public:
|
||||
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
|
||||
threadData.push_back( new _ThreadData( _graph->GetNumberOfNodes() ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const int last = ( int ) remainingNodes.size();
|
||||
@ -417,23 +418,25 @@ public:
|
||||
//
|
||||
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
||||
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
||||
|
||||
// INFO("rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree);
|
||||
//
|
||||
// INFO("rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree);
|
||||
|
||||
p.printStatus(numberOfContractedNodes);
|
||||
}
|
||||
|
||||
for ( unsigned threadNum = 0; threadNum < maxThreads; threadNum++ ) {
|
||||
delete threadData[threadNum];
|
||||
}
|
||||
}
|
||||
|
||||
template< class Edge >
|
||||
void GetEdges( std::vector< Edge >& edges ) {
|
||||
void GetEdges( DeallocatingVector< Edge >& edges ) {
|
||||
Percent p (_graph->GetNumberOfNodes());
|
||||
INFO("Getting edges of minimized graph");
|
||||
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
||||
if(oldNodeIDFromNewNodeIDMap.size()) {
|
||||
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; edge++ ) {
|
||||
p.printStatus(node);
|
||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
|
||||
const NodeID target = _graph->GetTarget( edge );
|
||||
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
|
||||
Edge newEdge;
|
||||
@ -456,7 +459,7 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
INFO("Renumbered remaining edges, freeing space");
|
||||
INFO("Renumbered edges of minimized graph, freeing space");
|
||||
_graph.reset();
|
||||
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
|
||||
INFO("Loading temporary edges");
|
||||
@ -468,7 +471,7 @@ public:
|
||||
//loads edges of graph before renumbering, no need for further numbering action.
|
||||
NodeID start;
|
||||
NodeID target;
|
||||
edges.reserve(edges.size()+numberOfTemporaryEdges);
|
||||
//edges.reserve(edges.size()+numberOfTemporaryEdges);
|
||||
_DynamicGraph::EdgeData data;
|
||||
for(unsigned i = 0; i < numberOfTemporaryEdges; ++i) {
|
||||
temporaryEdgeStorage.read((char*)&start, sizeof(NodeID));
|
||||
@ -535,18 +538,18 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
double _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, NodeID node){
|
||||
float _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, NodeID node){
|
||||
_ContractionInformation stats;
|
||||
|
||||
//perform simulated contraction
|
||||
_Contract< true> ( data, node, &stats );
|
||||
|
||||
// Result will contain the priority
|
||||
double result;
|
||||
float result;
|
||||
if ( stats.edgesDeleted == 0 || stats.originalEdgesDeleted == 0 )
|
||||
result = 1 * nodeData->depth;
|
||||
else
|
||||
result = 2 * ((( double ) stats.edgesAdded ) / stats.edgesDeleted ) + 4 * ((( double ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + 1 * nodeData->depth;
|
||||
result = 2 * ((( float ) stats.edgesAdded ) / stats.edgesDeleted ) + 4 * ((( float ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + 1 * nodeData->depth;
|
||||
assert( result >= 0 );
|
||||
return result;
|
||||
}
|
||||
@ -666,7 +669,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
bool _UpdateNeighbours( std::vector< double > & priorities, std::vector< _PriorityData > & nodeData, _ThreadData* const data, NodeID node) {
|
||||
bool _UpdateNeighbours( std::vector< float > & priorities, std::vector< _PriorityData > & nodeData, _ThreadData* const data, NodeID node) {
|
||||
std::vector< NodeID >& neighbours = data->neighbours;
|
||||
neighbours.clear();
|
||||
|
||||
@ -691,7 +694,7 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _IsIndependent( const std::vector< double >& priorities, const std::vector< _PriorityData >& nodeData, _ThreadData* const data, NodeID node ) {
|
||||
bool _IsIndependent( const std::vector< float >& priorities, const std::vector< _PriorityData >& nodeData, _ThreadData* const data, NodeID node ) {
|
||||
const double priority = priorities[node];
|
||||
|
||||
std::vector< NodeID >& neighbours = data->neighbours;
|
||||
@ -699,14 +702,17 @@ private:
|
||||
|
||||
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
|
||||
const NodeID target = _graph->GetTarget( e );
|
||||
if(node==target)
|
||||
continue;
|
||||
const double targetPriority = priorities[target];
|
||||
assert( targetPriority >= 0 );
|
||||
//found a neighbour with lower priority?
|
||||
if ( priority > targetPriority )
|
||||
return false;
|
||||
//tie breaking
|
||||
if ( priority == targetPriority && nodeData[node].bias < nodeData[target].bias )
|
||||
if ( priority == targetPriority && bias(node, target) ) {
|
||||
return false;
|
||||
}
|
||||
neighbours.push_back( target );
|
||||
}
|
||||
|
||||
@ -719,26 +725,44 @@ private:
|
||||
|
||||
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( u ) ; e < _graph->EndEdges( u ) ; ++e ) {
|
||||
const NodeID target = _graph->GetTarget( e );
|
||||
if(node==target)
|
||||
continue;
|
||||
|
||||
const double targetPriority = priorities[target];
|
||||
assert( targetPriority >= 0 );
|
||||
//found a neighbour with lower priority?
|
||||
if ( priority > targetPriority )
|
||||
if ( priority > targetPriority)
|
||||
return false;
|
||||
//tie breaking
|
||||
if ( priority == targetPriority && nodeData[node].bias < nodeData[target].bias )
|
||||
if ( priority == targetPriority && bias(node, target) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This bias function takes up 22 assembly instructions in total on X86
|
||||
*/
|
||||
inline bool bias(const NodeID a, const NodeID b) const {
|
||||
unsigned short hasha = fastHash(a);
|
||||
unsigned short hashb = fastHash(b);
|
||||
|
||||
//The compiler optimizes that to conditional register flags but without branching statements!
|
||||
if(hasha != hashb)
|
||||
return hasha < hashb;
|
||||
return a < b;
|
||||
}
|
||||
|
||||
boost::shared_ptr<_DynamicGraph> _graph;
|
||||
std::vector<_DynamicGraph::InputEdge> contractedEdges;
|
||||
std::string temporaryEdgeStorageFilename;
|
||||
std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
|
||||
long initialFilePosition;
|
||||
|
||||
XORFastHash fastHash;
|
||||
};
|
||||
|
||||
#endif // CONTRACTOR_H_INCLUDED
|
||||
|
@ -85,7 +85,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdg
|
||||
_trafficLights[id] = true;
|
||||
}
|
||||
|
||||
std::vector< _NodeBasedEdge > edges;
|
||||
DeallocatingVector< _NodeBasedEdge > edges;
|
||||
// edges.reserve( 2 * inputEdges.size() );
|
||||
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
|
||||
|
||||
@ -123,13 +123,13 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdg
|
||||
}
|
||||
}
|
||||
std::vector<NodeBasedEdge>().swap(inputEdges);
|
||||
std::vector<_NodeBasedEdge>(edges).swap(edges);
|
||||
//std::vector<_NodeBasedEdge>(edges).swap(edges);
|
||||
std::sort( edges.begin(), edges.end() );
|
||||
|
||||
_nodeBasedGraph.reset(new _NodeBasedDynamicGraph( nodes, edges ));
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::GetEdgeBasedEdges(std::vector< EdgeBasedEdge >& outputEdgeList ) {
|
||||
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
|
||||
GUARANTEE(0 == outputEdgeList.size(), "Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty");
|
||||
GUARANTEE(0 != edgeBasedEdges.size(), "No edges in edge based graph");
|
||||
|
||||
@ -255,9 +255,6 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
|
||||
//distance += heightPenalty;
|
||||
//distance += ComputeTurnPenalty(u, v, w);
|
||||
assert(edgeData1.edgeBasedNodeID != edgeData2.edgeBasedNodeID);
|
||||
if(edgeBasedEdges.size() == edgeBasedEdges.capacity()-3) {
|
||||
edgeBasedEdges.reserve(edgeBasedEdges.size()*1.2);
|
||||
}
|
||||
if(originalEdgeData.size() == originalEdgeData.capacity()-3) {
|
||||
originalEdgeData.reserve(originalEdgeData.size()*1.2);
|
||||
}
|
||||
@ -290,7 +287,9 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
|
||||
INFO("Removing duplicate nodes (if any)");
|
||||
edgeBasedNodes.erase( std::unique(edgeBasedNodes.begin(), edgeBasedNodes.end()), edgeBasedNodes.end() );
|
||||
INFO("Applying vector self-swap trick to free up memory");
|
||||
edgeBasedNodes.swap(edgeBasedNodes);
|
||||
INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
|
||||
std::vector<EdgeBasedNode>(edgeBasedNodes).swap(edgeBasedNodes);
|
||||
INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
|
||||
INFO("Node-based graph contains " << nodeBasedEdgeCounter << " edges");
|
||||
INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges, blowup is " << (double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter);
|
||||
INFO("Edge-based graph skipped " << numberOfSkippedTurns << " turns, defined by " << numberOfTurnRestrictions << " restrictions.");
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "../DataStructures/DeallocatingVector.h"
|
||||
#include "../DataStructures/DynamicGraph.h"
|
||||
#include "../DataStructures/ExtractorStructs.h"
|
||||
#include "../DataStructures/HashTable.h"
|
||||
@ -103,7 +104,7 @@ private:
|
||||
RestrictionMap _restrictionMap;
|
||||
|
||||
|
||||
std::vector<EdgeBasedEdge> edgeBasedEdges;
|
||||
DeallocatingVector<EdgeBasedEdge> edgeBasedEdges;
|
||||
std::vector<EdgeBasedNode> edgeBasedNodes;
|
||||
std::vector<OriginalEdgeData> originalEdgeData;
|
||||
std::vector<NodeInfo> inputNodeInfoList;
|
||||
@ -127,7 +128,7 @@ public:
|
||||
explicit EdgeBasedGraphFactory(int nodes, std::vector<InputEdgeT> & inputEdges, std::vector<NodeID> & _bollardNodes, std::vector<NodeID> & trafficLights, std::vector<_Restriction> & inputRestrictions, std::vector<NodeInfo> & nI, boost::property_tree::ptree speedProfile, std::string & srtm);
|
||||
|
||||
void Run(const char * originalEdgeDataFilename);
|
||||
void GetEdgeBasedEdges( std::vector< EdgeBasedEdge >& edges );
|
||||
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
||||
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
|
||||
void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData);
|
||||
short AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
|
||||
|
279
DataStructures/DeallocatingVector.h
Normal file
279
DataStructures/DeallocatingVector.h
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, others 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
*/
|
||||
|
||||
#ifndef DEALLOCATINGVECTOR_H_
|
||||
#define DEALLOCATINGVECTOR_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
#if __cplusplus > 199711L
|
||||
#define DEALLOCATION_VECTOR_NULL_PTR nullptr
|
||||
#else
|
||||
#define DEALLOCATION_VECTOR_NULL_PTR NULL
|
||||
#endif
|
||||
|
||||
|
||||
template<typename ElementT, size_t bucketSizeC = 10485760/sizeof(ElementT), bool DeallocateC = false>
|
||||
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> {
|
||||
protected:
|
||||
|
||||
struct DeallocatingVectorIteratorState {
|
||||
//make constructors explicit, so we do not mix random access and deallocation iterators.
|
||||
explicit DeallocatingVectorIteratorState() : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(-1) { assert(false); }
|
||||
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : mData(r.mData), mIndex(r.mIndex), mBucketList(r.mBucketList) {}
|
||||
//explicit DeallocatingVectorIteratorState(const ElementT * ptr, const size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
|
||||
explicit DeallocatingVectorIteratorState(const size_t idx, std::vector<ElementT *> & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) {
|
||||
setPointerForIndex();
|
||||
}
|
||||
ElementT * mData;
|
||||
size_t mIndex;
|
||||
std::vector<ElementT *> & mBucketList;
|
||||
inline void setPointerForIndex() {
|
||||
if(bucketSizeC*mBucketList.size() <= mIndex) {
|
||||
mData = DEALLOCATION_VECTOR_NULL_PTR;
|
||||
return;
|
||||
}
|
||||
size_t _bucket = mIndex/bucketSizeC;
|
||||
size_t _index = mIndex%bucketSizeC;
|
||||
mData = &(mBucketList[_bucket][_index]);
|
||||
|
||||
if(DeallocateC) {
|
||||
//if we hopped over the border of the previous bucket, then delete that bucket.
|
||||
if(0 == _index && _bucket) {
|
||||
delete[] mBucketList[_bucket-1];
|
||||
mBucketList[_bucket-1] = DEALLOCATION_VECTOR_NULL_PTR;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
|
||||
return (mData != other.mData) || (mIndex != other.mIndex) || (mBucketList != other.mBucketList);
|
||||
}
|
||||
|
||||
inline bool operator==(const DeallocatingVectorIteratorState &other) {
|
||||
return (mData == other.mData) && (mIndex == other.mIndex) && (mBucketList == other.mBucketList);
|
||||
}
|
||||
|
||||
inline bool operator<(const DeallocatingVectorIteratorState &other) {
|
||||
return mIndex < other.mIndex;
|
||||
}
|
||||
|
||||
//This is a hack to make assignment operator possible with reference member
|
||||
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
|
||||
if (this != &a) {
|
||||
this->DeallocatingVectorIteratorState::~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
|
||||
new (this) DeallocatingVectorIteratorState(a); // placement new
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
DeallocatingVectorIteratorState mState;
|
||||
|
||||
public:
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type value_type;
|
||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type difference_type;
|
||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
|
||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
|
||||
|
||||
DeallocatingVectorIterator() {}
|
||||
|
||||
template<typename T2>
|
||||
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
||||
DeallocatingVectorIterator(size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
||||
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
||||
|
||||
template<typename T2>
|
||||
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
||||
if(DeallocateC) assert(false);
|
||||
mState = r.mState; return *this;
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator& operator++() { //prefix
|
||||
// if(DeallocateC) assert(false);
|
||||
++mState.mIndex; mState.setPointerForIndex(); return *this;
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator& operator--() { //prefix
|
||||
if(DeallocateC) assert(false);
|
||||
--mState.mIndex; mState.setPointerForIndex(); return *this;
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator operator++(int) { //postfix
|
||||
DeallocatingVectorIteratorState _myState(mState);
|
||||
_myState.mIndex++; _myState.setPointerForIndex();
|
||||
return DeallocatingVectorIterator(_myState);
|
||||
}
|
||||
inline DeallocatingVectorIterator operator --(int) { //postfix
|
||||
if(DeallocateC) assert(false);
|
||||
DeallocatingVectorIteratorState _myState(mState);
|
||||
_myState.mIndex--; _myState.setPointerForIndex();
|
||||
return DeallocatingVectorIterator(_myState);
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
|
||||
DeallocatingVectorIteratorState _myState(mState);
|
||||
_myState.mIndex+=n; _myState.setPointerForIndex();
|
||||
return DeallocatingVectorIterator(_myState);
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator& operator+=(const difference_type& n) const {
|
||||
mState.mIndex+=n; return *this;
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
|
||||
if(DeallocateC) assert(false);
|
||||
DeallocatingVectorIteratorState _myState(mState);
|
||||
_myState.mIndex-=n; _myState.setPointerForIndex();
|
||||
return DeallocatingVectorIterator(_myState);
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
|
||||
if(DeallocateC) assert(false);
|
||||
mState.mIndex-=n; return *this;
|
||||
}
|
||||
inline reference operator*() const { return *mState.mData; }
|
||||
inline pointer operator->() const { return mState.mData; }
|
||||
inline reference operator[](const difference_type &n) const {
|
||||
if(DeallocateC) assert(false);
|
||||
DeallocatingVectorIteratorState _myState(mState);
|
||||
_myState.mIndex += n;
|
||||
_myState.setPointerForIndex;
|
||||
return _myState.mData;
|
||||
}
|
||||
|
||||
inline bool operator!=(const DeallocatingVectorIterator & other) {
|
||||
return mState != other.mState;
|
||||
}
|
||||
|
||||
inline bool operator==(const DeallocatingVectorIterator & other) {
|
||||
return mState == other.mState;
|
||||
}
|
||||
|
||||
bool operator<(const DeallocatingVectorIterator & other) {
|
||||
return mState < other.mState;
|
||||
}
|
||||
|
||||
difference_type operator-(const DeallocatingVectorIterator & other) {
|
||||
if(DeallocateC) assert(false);
|
||||
return mState.mIndex-other.mState.mIndex;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ElementT, size_t bucketSizeC = 10485760/sizeof(ElementT) >
|
||||
class DeallocatingVector {
|
||||
private:
|
||||
size_t mCurrentSize;
|
||||
std::vector<ElementT *> mBucketList;
|
||||
|
||||
public:
|
||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
|
||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
|
||||
|
||||
//this iterator deallocates all buckets that have been visited. Iterators to visited objects become invalid.
|
||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
|
||||
|
||||
DeallocatingVector() : mCurrentSize(0) {
|
||||
//initial bucket
|
||||
mBucketList.push_back(new ElementT[bucketSizeC]);
|
||||
}
|
||||
|
||||
~DeallocatingVector() {
|
||||
clear();
|
||||
}
|
||||
|
||||
inline void swap(DeallocatingVector<ElementT, bucketSizeC> & other) {
|
||||
std::swap(mCurrentSize, other.mCurrentSize);
|
||||
mBucketList.swap(other.mBucketList);
|
||||
}
|
||||
|
||||
inline void clear() {
|
||||
//Delete[]'ing ptr's to all Buckets
|
||||
for(unsigned i = 0; i < mBucketList.size(); ++i) {
|
||||
if(DEALLOCATION_VECTOR_NULL_PTR != mBucketList[i]) {
|
||||
delete[] (mBucketList[i]);
|
||||
}
|
||||
}
|
||||
//Removing all ptrs from vector
|
||||
std::vector<ElementT *>().swap(mBucketList);
|
||||
}
|
||||
|
||||
inline void push_back(const ElementT & element) {
|
||||
size_t _capacity = capacity();
|
||||
if(mCurrentSize == _capacity) {
|
||||
mBucketList.push_back(new ElementT[bucketSizeC]);
|
||||
}
|
||||
|
||||
size_t _index = size()%bucketSizeC;
|
||||
mBucketList.back()[_index] = element;
|
||||
++mCurrentSize;
|
||||
}
|
||||
|
||||
inline size_t size() const {
|
||||
return mCurrentSize;
|
||||
}
|
||||
|
||||
inline size_t capacity() const {
|
||||
return mBucketList.size() * bucketSizeC;
|
||||
}
|
||||
|
||||
inline iterator begin() {
|
||||
return iterator((size_t)0, mBucketList);
|
||||
}
|
||||
|
||||
inline iterator end() {
|
||||
return iterator(size(), mBucketList);
|
||||
}
|
||||
|
||||
inline deallocation_iterator dbegin() {
|
||||
return deallocation_iterator((size_t)0, mBucketList);
|
||||
}
|
||||
|
||||
inline deallocation_iterator dend() {
|
||||
return deallocation_iterator(size(), mBucketList);
|
||||
}
|
||||
|
||||
inline const_iterator begin() const {
|
||||
return const_iterator((size_t)0, mBucketList);
|
||||
}
|
||||
|
||||
inline const_iterator end() const {
|
||||
return const_iterator(size(), mBucketList);
|
||||
}
|
||||
|
||||
inline ElementT & operator[](const size_t index) {
|
||||
size_t _bucket = index / bucketSizeC;
|
||||
size_t _index = index % bucketSizeC;
|
||||
return (mBucketList[_bucket][_index]);
|
||||
}
|
||||
|
||||
const inline ElementT & operator[](const size_t index) const {
|
||||
size_t _bucket = index / bucketSizeC;
|
||||
size_t _index = index % bucketSizeC;
|
||||
return (mBucketList[_bucket][_index]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* DEALLOCATINGVECTOR_H_ */
|
@ -103,7 +103,7 @@ public:
|
||||
|
||||
/** Default constructor. target and weight are set to 0.*/
|
||||
EdgeBasedEdge() :
|
||||
_source(0), _target(0), _edgeID(0)/*, _nameID1(0)*/, _weight(0), _forward(0), _backward(0)/*, _turnInstruction(0)*/ { assert(false); } //shall not be used.
|
||||
_source(0), _target(0), _edgeID(0), _weight(0), _forward(false), _backward(false) { }
|
||||
|
||||
explicit EdgeBasedEdge(NodeID s, NodeID t, NodeID v, EdgeWeight w, bool f, bool b) :
|
||||
_source(s), _target(t), _edgeID(v), _weight(w), _forward(f), _backward(b){}
|
||||
|
@ -42,25 +42,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
|
||||
#include "ExtractorStructs.h"
|
||||
#include "GridEdge.h"
|
||||
#include "LRUCache.h"
|
||||
#include "Percent.h"
|
||||
#include "PhantomNodes.h"
|
||||
#include "Util.h"
|
||||
#include "StaticGraph.h"
|
||||
#include "../Algorithms/Bresenham.h"
|
||||
|
||||
static const unsigned MAX_CACHE_ELEMENTS = 1000;
|
||||
|
||||
namespace NNGrid{
|
||||
|
||||
//struct IdenticalHashFunction {
|
||||
//public:
|
||||
// inline unsigned operator ()(const unsigned value) const {
|
||||
// return value;
|
||||
// }
|
||||
//};
|
||||
|
||||
|
||||
static boost::thread_specific_ptr<std::ifstream> localStream;
|
||||
|
||||
template<bool WriteAccess = false>
|
||||
@ -99,7 +88,7 @@ public:
|
||||
}
|
||||
|
||||
template<typename EdgeT>
|
||||
void ConstructGrid(std::vector<EdgeT> & edgeList, char * ramIndexOut, char * fileIndexOut) {
|
||||
inline void ConstructGrid(std::vector<EdgeT> & edgeList, char * ramIndexOut, char * fileIndexOut) {
|
||||
//TODO: Implement this using STXXL-Streams
|
||||
#ifndef ROUTED
|
||||
Percent p(edgeList.size());
|
||||
@ -141,7 +130,7 @@ public:
|
||||
entriesInFileWithRAMSameIndex.push_back(gridEntry);
|
||||
}
|
||||
cellMap.clear();
|
||||
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
|
||||
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
|
||||
/*unsigned numberOfBytesInCell = */FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
|
||||
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
|
||||
entriesInFileWithRAMSameIndex.clear();
|
||||
@ -324,7 +313,7 @@ private:
|
||||
return (std::fabs(d1 - d2) < 0.0001);
|
||||
}
|
||||
|
||||
unsigned FillCell(std::vector<GridEntry>& entriesWithSameRAMIndex, const unsigned long fileOffset, boost::unordered_map< unsigned, unsigned > & cellMap ) {
|
||||
inline unsigned FillCell(std::vector<GridEntry>& entriesWithSameRAMIndex, const unsigned long fileOffset, boost::unordered_map< unsigned, unsigned > & cellMap ) {
|
||||
std::vector<char> tmpBuffer(32*32*4096,0);
|
||||
unsigned long indexIntoTmpBuffer = 0;
|
||||
unsigned numberOfWrittenBytes = 0;
|
||||
@ -376,7 +365,7 @@ private:
|
||||
return numberOfWrittenBytes;
|
||||
}
|
||||
|
||||
unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector<GridEntry> &vectorWithSameFileIndex, std::vector<char> & tmpBuffer, const unsigned long index) {
|
||||
inline unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector<GridEntry> &vectorWithSameFileIndex, std::vector<char> & tmpBuffer, const unsigned long index) const {
|
||||
sort( vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end() );
|
||||
vectorWithSameFileIndex.erase(unique(vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end()), vectorWithSameFileIndex.end());
|
||||
const unsigned lengthOfBucket = vectorWithSameFileIndex.size();
|
||||
@ -472,7 +461,7 @@ private:
|
||||
localStream->read((char *)&result[currentSizeOfResult], lengthOfBucket*sizeof(_GridEdge));
|
||||
}
|
||||
|
||||
void AddEdge(const _GridEdge & edge) {
|
||||
inline void AddEdge(const _GridEdge & edge) {
|
||||
#ifndef ROUTED
|
||||
std::vector<BresenhamPixel> indexList;
|
||||
GetListOfIndexesForEdgeAndGridSize(edge.startCoord, edge.targetCoord, indexList);
|
||||
@ -521,7 +510,7 @@ private:
|
||||
return (p-x)*(p-x) + (q-y)*(q-y);
|
||||
}
|
||||
|
||||
void GetListOfIndexesForEdgeAndGridSize(const _Coordinate& start, const _Coordinate& target, std::vector<BresenhamPixel> &indexList) const {
|
||||
inline void GetListOfIndexesForEdgeAndGridSize(const _Coordinate& start, const _Coordinate& target, std::vector<BresenhamPixel> &indexList) const {
|
||||
double lat1 = start.lat/100000.;
|
||||
double lon1 = start.lon/100000.;
|
||||
|
||||
|
67
DataStructures/XORFastHash.h
Normal file
67
DataStructures/XORFastHash.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, others 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
*/
|
||||
|
||||
#ifndef FASTXORHASH_H_
|
||||
#define FASTXORHASH_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
This is an implementation of Tabulation hashing, which has suprising properties like universality.
|
||||
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
|
||||
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
|
||||
|
||||
1: movq table2(%rip), %rdx
|
||||
2: movl %edi, %eax
|
||||
3: movzwl %di, %edi
|
||||
4: shrl $16, %eax
|
||||
5: movzwl %ax, %eax
|
||||
6: movzbl (%rdx,%rax), %eax
|
||||
7: movq table1(%rip), %rdx
|
||||
8: xorb (%rdx,%rdi), %al
|
||||
9: movzbl %al, %eax
|
||||
10: ret
|
||||
|
||||
*/
|
||||
class XORFastHash {
|
||||
std::vector<unsigned char> table1;
|
||||
std::vector<unsigned char> table2;
|
||||
public:
|
||||
XORFastHash() {
|
||||
table1.resize(1 << 16);
|
||||
table2.resize(1 << 16);
|
||||
for(unsigned i = 0; i < (1 << 16); ++i) {
|
||||
table1[i] = i; table2[i];
|
||||
}
|
||||
std::random_shuffle(table1.begin(), table1.end());
|
||||
std::random_shuffle(table2.begin(), table2.end());
|
||||
}
|
||||
unsigned short operator()(const unsigned originalValue) const {
|
||||
unsigned short lsb = ((originalValue) & 0xffff);
|
||||
unsigned short msb = (((originalValue) >> 16) & 0xffff);
|
||||
return table1[lsb] ^ table2[msb];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* FASTXORHASH_H_ */
|
@ -43,6 +43,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#include "Contractor/Contractor.h"
|
||||
#include "Contractor/EdgeBasedGraphFactory.h"
|
||||
#include "DataStructures/BinaryHeap.h"
|
||||
#include "DataStructures/DeallocatingVector.h"
|
||||
#include "DataStructures/ExtractorStructs.h"
|
||||
#include "DataStructures/NNGrid.h"
|
||||
#include "DataStructures/QueryEdge.h"
|
||||
@ -125,21 +126,14 @@ int main (int argc, char *argv[]) {
|
||||
INFO("Generating edge-expanded graph representation");
|
||||
EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile, SRTM_ROOT);
|
||||
std::vector<ImportEdge>().swap(edgeList);
|
||||
|
||||
edgeBasedGraphFactory->Run(edgeOut);
|
||||
std::vector<_Restriction>().swap(inputRestrictions);
|
||||
std::vector<NodeID>().swap(bollardNodes);
|
||||
std::vector<NodeID>().swap(trafficLightNodes);
|
||||
NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
|
||||
std::vector<EdgeBasedEdge> edgeBasedEdgeList;
|
||||
DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
|
||||
edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
|
||||
|
||||
// stxxl::vector<EdgeBasedEdge> externalEdgeBasedEdgeList;
|
||||
// BOOST_FOREACH(EdgeBasedEdge & edge, edgeBasedEdgeList) {
|
||||
// externalEdgeBasedEdgeList.push_back(edge);
|
||||
// }
|
||||
// std::vector<EdgeBasedEdge>().swap(edgeBasedEdgeList);
|
||||
|
||||
/***
|
||||
* Writing info on original (node-based) nodes
|
||||
*/
|
||||
@ -191,7 +185,7 @@ int main (int argc, char *argv[]) {
|
||||
contractor->Run();
|
||||
INFO("Contraction took " << get_timestamp() - contractionStartedTimestamp << " sec");
|
||||
|
||||
std::vector< QueryEdge > contractedEdgeList;
|
||||
DeallocatingVector< QueryEdge > contractedEdgeList;
|
||||
contractor->GetEdges( contractedEdgeList );
|
||||
delete contractor;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user