Some performance hacks in nearest neighbor lookup. gives upto 10% of

speed on the single operation.
This commit is contained in:
DennisOSRM 2012-02-24 11:16:22 +01:00
parent e6ce9d3d29
commit 1f381d790f

View File

@ -53,6 +53,14 @@ 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>
@ -149,34 +157,42 @@ public:
}
bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode) {
double time1 = get_timestamp();
bool foundNode = false;
_Coordinate startCoord(100000*(lat2y(static_cast<double>(location.lat)/100000.)), location.lon);
/** search for point on edge close to source */
unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_GridEdge> candidates;
double time2 = get_timestamp();
boost::unordered_map< unsigned, unsigned, IdenticalHashFunction > cellMap;
for(int j = -32768; j < (32768+1); j+=32768) {
for(int i = -1; i < 2; i++){
GetContentsOfFileBucket(fileIndex+i+j, candidates);
GetContentsOfFileBucket(fileIndex+i+j, candidates, cellMap);
}
}
double time3 = get_timestamp();
_GridEdge smallestEdge;
_Coordinate tmp, newEndpoint;
_Coordinate tmp;
double dist = numeric_limits<double>::max();
double time4 = get_timestamp();
INFO("candidates.size(): " << candidates.size() );
double r, tmpDist;
BOOST_FOREACH(_GridEdge candidate, candidates) {
double r = 0.;
double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
r = 0.;
tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
if(tmpDist < dist && !DoubleEpsilonCompare(dist, tmpDist)) {
//INFO("a) " << candidate.edgeBasedNode << ", dist: " << tmpDist);
resultNode.Reset();
dist = tmpDist;
resultNode.edgeBasedNode = candidate.edgeBasedNode;
resultNode.nodeBasedEdgeNameID = candidate.nameID;
resultNode.weight1 = candidate.weight;
dist = tmpDist;
resultNode.location.lat = round(100000.*(y2lat(static_cast<double>(tmp.lat)/100000.)));
resultNode.weight2 = INT_MAX;
resultNode.location.lat = tmp.lat;
resultNode.location.lon = tmp.lon;
foundNode = true;
smallestEdge = candidate;
newEndpoint = tmp;
//} else if(tmpDist < dist) {
//INFO("a) ignored " << candidate.edgeBasedNode << " at distance " << std::fabs(dist - tmpDist));
} else if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs((int)candidate.edgeBasedNode-(int)resultNode.edgeBasedNode)) {
@ -184,6 +200,9 @@ public:
//INFO("b) " << candidate.edgeBasedNode << ", dist: " << tmpDist);
}
}
resultNode.location.lat = round(100000.*(y2lat(static_cast<double>(resultNode.location.lat)/100000.)));
double time5 = get_timestamp();
// INFO("startcoord: " << smallestEdge.startCoord << ", tgtcoord" << smallestEdge.targetCoord << "result: " << newEndpoint);
// INFO("length of old edge: " << ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
// INFO("Length of new edge: " << ApproximateDistance(smallestEdge.startCoord, newEndpoint));
@ -193,23 +212,30 @@ public:
// INFO("-> node: " << resultNode.edgeBasedNode << ", bidir: " << (resultNode.isBidirected() ? "yes" : "no"));
// }
// INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << ", newEndpoint: " << newEndpoint);
double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, newEndpoint)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0);
// INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << ", newEndpoint: " << newEndpoint);
double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0);
// INFO("Length of vector: " << ApproximateDistance(smallestEdge.startCoord, newEndpoint)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
// INFO("Length of vector: " << ApproximateDistance(smallestEdge.startCoord, newEndpoint)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
//Hack to fix rounding errors and wandering via nodes.
if(std::abs(location.lon - resultNode.location.lon) == 1)
resultNode.location.lon = location.lon;
if(std::abs(location.lat - resultNode.location.lat) == 1)
resultNode.location.lat = location.lat;
resultNode.location.lat = location.lat;
resultNode.weight1 *= ratio;
if(INT_MAX != resultNode.weight2) {
resultNode.weight2 -= resultNode.weight1;
}
resultNode.ratio = ratio;
// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio);
// INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no") << "\n--");
// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio);
// INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no") << "\n--");
double time6 = get_timestamp();
INFO("init1: " << (time2-time1)*1000);
INFO("i/os: " << (time3-time2)*1000);
INFO("init2: " << (time4-time3)*1000);
INFO("mins: " << (time5-time4)*1000);
INFO("rest: " << (time6-time5)*1000);
INFO("compl: " << (time6-time1)*1000);
return foundNode;
}
@ -222,9 +248,10 @@ public:
void FindNearestCoordinateOnEdgeInNodeBasedGraph(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate) {
unsigned fileIndex = GetFileIndexForLatLon(100000*(lat2y(static_cast<double>(inputCoordinate.lat)/100000.)), inputCoordinate.lon);
std::vector<_GridEdge> candidates;
boost::unordered_map< unsigned, unsigned, IdenticalHashFunction > cellMap;
for(int j = -32768; j < (32768+1); j+=32768) {
for(int i = -1; i < 2; i++) {
GetContentsOfFileBucket(fileIndex+i+j, candidates);
GetContentsOfFileBucket(fileIndex+i+j, candidates, cellMap);
}
}
_Coordinate tmp;
@ -245,9 +272,10 @@ public:
unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_GridEdge> candidates;
boost::unordered_map< unsigned, unsigned, IdenticalHashFunction > cellMap;
for(int j = -32768; j < (32768+1); j+=32768) {
for(int i = -1; i < 2; i++) {
GetContentsOfFileBucket(fileIndex+i+j, candidates);
GetContentsOfFileBucket(fileIndex+i+j, candidates, cellMap);
}
}
_Coordinate tmp;
@ -265,18 +293,29 @@ public:
private:
inline void BuildCellIndexToFileIndexMap(const unsigned ramIndex, boost::unordered_map<unsigned ,unsigned >& cellMap){
inline void BuildCellIndexToFileIndexMap(const unsigned ramIndex, boost::unordered_map<unsigned, unsigned, IdenticalHashFunction >& cellMap){
// double time1 = get_timestamp();
unsigned lineBase = ramIndex/1024;
lineBase = lineBase*32*32768;
unsigned columnBase = ramIndex%1024;
columnBase=columnBase*32;
std::vector<std::pair<unsigned, unsigned> >insertionVector(1024);
// double time2 = get_timestamp();
for (int i = 0;i < 32;++i) {
for (int j = 0;j < 32;++j) {
unsigned fileIndex = lineBase + i * 32768 + columnBase + j;
unsigned cellIndex = i * 32 + j;
cellMap[fileIndex] = cellIndex;
// cellMap[fileIndex] = cellIndex;
insertionVector[i * 32 + j] = std::make_pair(fileIndex, cellIndex);
}
}
// double time3 = get_timestamp();
cellMap.insert(insertionVector.begin(), insertionVector.end());
// double time4 = get_timestamp();
// INFO(" init: " << (time2-time1)*1000);
// INFO(" vect: " << (time3-time2)*1000);
// INFO(" inse: " << (time4-time3)*1000);
}
inline bool DoubleEpsilonCompare(const double d1, const double d2) {
@ -290,7 +329,7 @@ private:
assert(indexOutFile.is_open());
vector<unsigned long> cellIndex(32*32,ULONG_MAX);
boost::unordered_map< unsigned, unsigned > cellMap(1024);
boost::unordered_map< unsigned, unsigned, IdenticalHashFunction > cellMap(1024);
unsigned ramIndex = entriesWithSameRAMIndex.begin()->ramIndex;
BuildCellIndexToFileIndexMap(ramIndex, cellMap);
@ -368,7 +407,7 @@ private:
return counter;
}
void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_GridEdge>& result) {
inline void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_GridEdge>& result, boost::unordered_map< unsigned, unsigned, IdenticalHashFunction > & cellMap) {
unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
unsigned long startIndexInFile = ramIndexTable[ramIndex];
if(startIndexInFile == ULONG_MAX) {
@ -377,7 +416,7 @@ private:
unsigned long cellIndex[32*32];
boost::unordered_map< unsigned, unsigned > cellMap(1024);
cellMap.clear();
BuildCellIndexToFileIndexMap(ramIndex, cellMap);
if(!localStream.get() || !localStream->is_open()) {
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
@ -389,11 +428,11 @@ private:
localStream->seekg(startIndexInFile);
localStream->read((char*) cellIndex, 32*32*sizeof(unsigned long));
assert(cellMap.find(fileIndex) != cellMap.end());
if(cellIndex[cellMap.find(fileIndex)->second] == ULONG_MAX) {
assert(cellMap.find(fileIndex) != cellMap.end());
if(cellIndex[cellMap[fileIndex]] == ULONG_MAX) {
return;
}
const unsigned long position = cellIndex[cellMap.find(fileIndex)->second] + 32*32*sizeof(unsigned long) ;
const unsigned long position = cellIndex[cellMap[fileIndex]] + 32*32*sizeof(unsigned long) ;
localStream->seekg(position);
_GridEdge gridEdge;
@ -403,7 +442,7 @@ private:
break;
result.push_back(gridEdge);
} while(true);
}
}
void AddEdge(_GridEdge edge) {
#ifndef ROUTED
@ -505,10 +544,6 @@ private:
return ramIndex;
}
inline int signum(int x){
return (x > 0) ? 1 : (x < 0) ? -1 : 0;
}
const static unsigned long END_OF_BUCKET_DELIMITER = UINT_MAX;
ofstream indexOutFile;