mirror of
https://github.com/introlab/rtabmap_ros.git
synced 2026-10-04 00:37:46 +08:00
Renamed all flann headers to avoid conflicts if flann is already installed on the computer
This commit is contained in:
@@ -386,12 +386,6 @@ IF(OpenCV_FOUND)
|
||||
ENDIF()
|
||||
ENDIF(OpenCV_FOUND)
|
||||
|
||||
IF(FLANN18_FOUND)
|
||||
MESSAGE(STATUS " With FLANN >= 1.8 = YES")
|
||||
ELSE()
|
||||
MESSAGE(STATUS " With FLANN >= 1.8 = NO")
|
||||
ENDIF()
|
||||
|
||||
IF(Freenect_FOUND)
|
||||
MESSAGE(STATUS " With Freenect = YES")
|
||||
ELSEIF(NOT WITH_FREENECT)
|
||||
|
||||
@@ -57,8 +57,8 @@ SET(SRC_FILES
|
||||
toro3d/posegraph2.cpp
|
||||
toro3d/treeoptimizer2.cpp
|
||||
|
||||
flann/ext/lz4.c
|
||||
flann/ext/lz4hc.c
|
||||
rtflann/ext/lz4.c
|
||||
rtflann/ext/lz4hc.c
|
||||
|
||||
sqlite3/sqlite3.c
|
||||
)
|
||||
|
||||
@@ -45,7 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "flann/flann.hpp"
|
||||
#include "rtflann/flann.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
@@ -75,11 +75,11 @@ public:
|
||||
{
|
||||
if(featuresType_ == CV_8UC1)
|
||||
{
|
||||
delete (flann::Index<flann::Hamming<unsigned char> >*)index_;
|
||||
delete (rtflann::Index<rtflann::Hamming<unsigned char> >*)index_;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete (flann::Index<flann::L2<float> >*)index_;
|
||||
delete (rtflann::Index<rtflann::L2<float> >*)index_;
|
||||
}
|
||||
index_ = 0;
|
||||
}
|
||||
@@ -95,11 +95,11 @@ public:
|
||||
}
|
||||
if(featuresType_ == CV_8UC1)
|
||||
{
|
||||
return ((const flann::Index<flann::Hamming<unsigned char> >*)index_)->size();
|
||||
return ((const rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->size();
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((const flann::Index<flann::L2<float> >*)index_)->size();
|
||||
return ((const rtflann::Index<rtflann::L2<float> >*)index_)->size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,17 +112,17 @@ public:
|
||||
}
|
||||
if(featuresType_ == CV_8UC1)
|
||||
{
|
||||
return ((const flann::Index<flann::Hamming<unsigned char> >*)index_)->usedMemory()/1000;
|
||||
return ((const rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->usedMemory()/1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((const flann::Index<flann::L2<float> >*)index_)->usedMemory()/1000;
|
||||
return ((const rtflann::Index<rtflann::L2<float> >*)index_)->usedMemory()/1000;
|
||||
}
|
||||
}
|
||||
|
||||
void build(
|
||||
const cv::Mat & features,
|
||||
const flann::IndexParams& params)
|
||||
const rtflann::IndexParams& params)
|
||||
{
|
||||
this->release();
|
||||
UASSERT(index_ == 0);
|
||||
@@ -132,15 +132,15 @@ public:
|
||||
|
||||
if(featuresType_ == CV_8UC1)
|
||||
{
|
||||
flann::Matrix<unsigned char> dataset(features.data, features.rows, features.cols);
|
||||
index_ = new flann::Index<flann::Hamming<unsigned char> >(dataset, params);
|
||||
((flann::Index<flann::Hamming<unsigned char> >*)index_)->buildIndex();
|
||||
rtflann::Matrix<unsigned char> dataset(features.data, features.rows, features.cols);
|
||||
index_ = new rtflann::Index<rtflann::Hamming<unsigned char> >(dataset, params);
|
||||
((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->buildIndex();
|
||||
}
|
||||
else
|
||||
{
|
||||
flann::Matrix<float> dataset((float*)features.data, features.rows, features.cols);
|
||||
index_ = new flann::Index<flann::L2<float> >(dataset, params);
|
||||
((flann::Index<flann::L2<float> >*)index_)->buildIndex();
|
||||
rtflann::Matrix<float> dataset((float*)features.data, features.rows, features.cols);
|
||||
index_ = new rtflann::Index<rtflann::L2<float> >(dataset, params);
|
||||
((rtflann::Index<rtflann::L2<float> >*)index_)->buildIndex();
|
||||
}
|
||||
nextIndex_ = features.rows;
|
||||
}
|
||||
@@ -165,13 +165,13 @@ public:
|
||||
UASSERT(feature.rows == 1);
|
||||
if(featuresType_ == CV_8UC1)
|
||||
{
|
||||
flann::Matrix<unsigned char> dataset(feature.data, feature.rows, feature.cols);
|
||||
((flann::Index<flann::Hamming<unsigned char> >*)index_)->addPoints(dataset);
|
||||
rtflann::Matrix<unsigned char> dataset(feature.data, feature.rows, feature.cols);
|
||||
((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->addPoints(dataset);
|
||||
}
|
||||
else
|
||||
{
|
||||
flann::Matrix<float> dataset((float*)feature.data, feature.rows, feature.cols);
|
||||
((flann::Index<flann::L2<float> >*)index_)->addPoints(dataset);
|
||||
rtflann::Matrix<float> dataset((float*)feature.data, feature.rows, feature.cols);
|
||||
((rtflann::Index<rtflann::L2<float> >*)index_)->addPoints(dataset);
|
||||
}
|
||||
return nextIndex_++;
|
||||
}
|
||||
@@ -191,11 +191,11 @@ public:
|
||||
|
||||
if(featuresType_ == CV_8UC1)
|
||||
{
|
||||
((flann::Index<flann::Hamming<unsigned char> >*)index_)->removePoint(index);
|
||||
((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->removePoint(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
((flann::Index<flann::L2<float> >*)index_)->removePoint(index);
|
||||
((rtflann::Index<rtflann::L2<float> >*)index_)->removePoint(index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ public:
|
||||
cv::Mat & indices,
|
||||
cv::Mat & dists,
|
||||
int knn,
|
||||
const flann::SearchParams& params=flann::SearchParams())
|
||||
const rtflann::SearchParams& params=rtflann::SearchParams())
|
||||
{
|
||||
if(!index_)
|
||||
{
|
||||
@@ -214,19 +214,19 @@ public:
|
||||
indices.create(query.rows, knn, CV_32S);
|
||||
dists.create(query.rows, knn, featuresType_ == CV_8UC1?CV_32S:CV_32F);
|
||||
|
||||
flann::Matrix<int> indicesF((int*)indices.data, indices.rows, indices.cols);
|
||||
rtflann::Matrix<int> indicesF((int*)indices.data, indices.rows, indices.cols);
|
||||
|
||||
if(featuresType_ == CV_8UC1)
|
||||
{
|
||||
flann::Matrix<unsigned int> distsF((unsigned int*)dists.data, dists.rows, dists.cols);
|
||||
flann::Matrix<unsigned char> queryF(query.data, query.rows, query.cols);
|
||||
((flann::Index<flann::Hamming<unsigned char> >*)index_)->knnSearch(queryF, indicesF, distsF, knn, params);
|
||||
rtflann::Matrix<unsigned int> distsF((unsigned int*)dists.data, dists.rows, dists.cols);
|
||||
rtflann::Matrix<unsigned char> queryF(query.data, query.rows, query.cols);
|
||||
((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->knnSearch(queryF, indicesF, distsF, knn, params);
|
||||
}
|
||||
else
|
||||
{
|
||||
flann::Matrix<float> distsF((float*)dists.data, dists.rows, dists.cols);
|
||||
flann::Matrix<float> queryF((float*)query.data, query.rows, query.cols);
|
||||
((flann::Index<flann::L2<float> >*)index_)->knnSearch(queryF, indicesF, distsF, knn, params);
|
||||
rtflann::Matrix<float> distsF((float*)dists.data, dists.rows, dists.cols);
|
||||
rtflann::Matrix<float> queryF((float*)query.data, query.rows, query.cols);
|
||||
((rtflann::Index<rtflann::L2<float> >*)index_)->knnSearch(queryF, indicesF, distsF, knn, params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,15 +517,15 @@ void VWDictionary::update()
|
||||
switch(_strategy)
|
||||
{
|
||||
case kNNFlannNaive:
|
||||
_flannIndex->build(w->getDescriptor(), flann::LinearIndexParams());
|
||||
_flannIndex->build(w->getDescriptor(), rtflann::LinearIndexParams());
|
||||
break;
|
||||
case kNNFlannKdTree:
|
||||
UASSERT_MSG(w->getDescriptor().type() == CV_32F, "To use KdTree dictionary, float descriptors are required!");
|
||||
_flannIndex->build(w->getDescriptor(), flann::KDTreeIndexParams());
|
||||
_flannIndex->build(w->getDescriptor(), rtflann::KDTreeIndexParams());
|
||||
break;
|
||||
case kNNFlannLSH:
|
||||
UASSERT_MSG(w->getDescriptor().type() == CV_8U, "To use LSH dictionary, binary descriptors are required!");
|
||||
_flannIndex->build(w->getDescriptor(), flann::LshIndexParams(12, 20, 2));
|
||||
_flannIndex->build(w->getDescriptor(), rtflann::LshIndexParams(12, 20, 2));
|
||||
break;
|
||||
default:
|
||||
UFATAL("Not supposed to be here!");
|
||||
@@ -607,15 +607,15 @@ void VWDictionary::update()
|
||||
switch(_strategy)
|
||||
{
|
||||
case kNNFlannNaive:
|
||||
_flannIndex->build(_dataTree, flann::LinearIndexParams());
|
||||
_flannIndex->build(_dataTree, rtflann::LinearIndexParams());
|
||||
break;
|
||||
case kNNFlannKdTree:
|
||||
UASSERT_MSG(type == CV_32F, "To use KdTree dictionary, float descriptors are required!");
|
||||
_flannIndex->build(_dataTree, flann::KDTreeIndexParams());
|
||||
_flannIndex->build(_dataTree, rtflann::KDTreeIndexParams());
|
||||
break;
|
||||
case kNNFlannLSH:
|
||||
UASSERT_MSG(type == CV_8U, "To use LSH dictionary, binary descriptors are required!");
|
||||
_flannIndex->build(_dataTree, flann::LshIndexParams(12, 20, 2));
|
||||
_flannIndex->build(_dataTree, rtflann::LshIndexParams(12, 20, 2));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -1,842 +0,0 @@
|
||||
/**********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2011 Andreas Muetzel ([email protected]). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#include "kdtree_cuda_3d_index.h"
|
||||
#include <flann/algorithms/dist.h>
|
||||
#include <flann/util/cuda/result_set.h>
|
||||
// #define THRUST_DEBUG 1
|
||||
#include <cuda.h>
|
||||
#include <thrust/copy.h>
|
||||
#include <thrust/device_vector.h>
|
||||
#include <vector_types.h>
|
||||
#include <flann/util/cutil_math.h>
|
||||
#include <thrust/host_vector.h>
|
||||
#include <thrust/copy.h>
|
||||
#include <flann/util/cuda/heap.h>
|
||||
#include <thrust/scan.h>
|
||||
#include <thrust/count.h>
|
||||
#include <flann/algorithms/kdtree_cuda_builder.h>
|
||||
#include <vector_types.h>
|
||||
namespace flann
|
||||
{
|
||||
|
||||
namespace KdTreeCudaPrivate
|
||||
{
|
||||
template< typename GPUResultSet, typename Distance >
|
||||
__device__
|
||||
void searchNeighbors(const cuda::kd_tree_builder_detail::SplitInfo* splits,
|
||||
const int* child1,
|
||||
const int* parent,
|
||||
const float4* aabbLow,
|
||||
const float4* aabbHigh, const float4* elements, const float4& q, GPUResultSet& result, const Distance& distance = Distance() )
|
||||
{
|
||||
|
||||
bool backtrack=false;
|
||||
int lastNode=-1;
|
||||
int current=0;
|
||||
|
||||
cuda::kd_tree_builder_detail::SplitInfo split;
|
||||
while(true) {
|
||||
if( current==-1 ) break;
|
||||
split = splits[current];
|
||||
|
||||
float diff1;
|
||||
if( split.split_dim==0 ) diff1=q.x- split.split_val;
|
||||
else if( split.split_dim==1 ) diff1=q.y- split.split_val;
|
||||
else if( split.split_dim==2 ) diff1=q.z- split.split_val;
|
||||
|
||||
// children are next to each other: leftChild+1 == rightChild
|
||||
int leftChild= child1[current];
|
||||
int bestChild=leftChild;
|
||||
int otherChild=leftChild;
|
||||
|
||||
if ((diff1)<0) {
|
||||
otherChild++;
|
||||
}
|
||||
else {
|
||||
bestChild++;
|
||||
}
|
||||
|
||||
if( !backtrack ) {
|
||||
/* If this is a leaf node, then do check and return. */
|
||||
if (leftChild==-1) {
|
||||
for (int i=split.left; i<split.right; ++i) {
|
||||
float dist=distance.dist(elements[i],q);
|
||||
result.insert(i,dist);
|
||||
}
|
||||
backtrack=true;
|
||||
lastNode=current;
|
||||
current=parent[current];
|
||||
}
|
||||
else { // go to closer child node
|
||||
lastNode=current;
|
||||
current=bestChild;
|
||||
}
|
||||
}
|
||||
else { // continue moving back up the tree or visit far node?
|
||||
// minimum possible distance between query point and a point inside the AABB
|
||||
float mindistsq=0;
|
||||
float4 aabbMin=aabbLow[otherChild];
|
||||
float4 aabbMax=aabbHigh[otherChild];
|
||||
|
||||
if( q.x < aabbMin.x ) mindistsq+=distance.axisDist(q.x, aabbMin.x);
|
||||
else if( q.x > aabbMax.x ) mindistsq+=distance.axisDist(q.x, aabbMax.x);
|
||||
if( q.y < aabbMin.y ) mindistsq+=distance.axisDist(q.y, aabbMin.y);
|
||||
else if( q.y > aabbMax.y ) mindistsq+=distance.axisDist(q.y, aabbMax.y);
|
||||
if( q.z < aabbMin.z ) mindistsq+=distance.axisDist(q.z, aabbMin.z);
|
||||
else if( q.z > aabbMax.z ) mindistsq+=distance.axisDist(q.z, aabbMax.z);
|
||||
|
||||
// the far node was NOT the last node (== not visited yet) AND there could be a closer point in it
|
||||
if(( lastNode==bestChild) && (mindistsq <= result.worstDist() ) ) {
|
||||
lastNode=current;
|
||||
current=otherChild;
|
||||
backtrack=false;
|
||||
}
|
||||
else {
|
||||
lastNode=current;
|
||||
current=parent[current];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template< typename GPUResultSet, typename Distance >
|
||||
__global__
|
||||
void nearestKernel(const cuda::kd_tree_builder_detail::SplitInfo* splits,
|
||||
const int* child1,
|
||||
const int* parent,
|
||||
const float4* aabbMin,
|
||||
const float4* aabbMax, const float4* elements, const float* query, int stride, int resultStride, int* resultIndex, float* resultDist, int querysize, GPUResultSet result, Distance dist = Distance())
|
||||
{
|
||||
typedef float DistanceType;
|
||||
typedef float ElementType;
|
||||
// typedef DistanceType float;
|
||||
size_t tid = blockDim.x*blockIdx.x + threadIdx.x;
|
||||
|
||||
if( tid >= querysize ) return;
|
||||
|
||||
float4 q = make_float4(query[tid*stride],query[tid*stride+1],query[tid*stride+2],0);
|
||||
|
||||
result.setResultLocation( resultDist, resultIndex, tid, resultStride );
|
||||
|
||||
searchNeighbors(splits,child1,parent,aabbMin,aabbMax,elements, q, result, dist);
|
||||
|
||||
result.finish();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//! contains some pointers that use cuda data types and that cannot be easily
|
||||
//! forward-declared.
|
||||
//! basically it contains all GPU buffers
|
||||
template<typename Distance>
|
||||
struct KDTreeCuda3dIndex<Distance>::GpuHelper
|
||||
{
|
||||
thrust::device_vector< cuda::kd_tree_builder_detail::SplitInfo >* gpu_splits_;
|
||||
thrust::device_vector< int >* gpu_parent_;
|
||||
thrust::device_vector< int >* gpu_child1_;
|
||||
thrust::device_vector< float4 >* gpu_aabb_min_;
|
||||
thrust::device_vector< float4 >* gpu_aabb_max_;
|
||||
thrust::device_vector<float4>* gpu_points_;
|
||||
thrust::device_vector<int>* gpu_vind_;
|
||||
GpuHelper() : gpu_splits_(0), gpu_parent_(0), gpu_child1_(0), gpu_aabb_min_(0), gpu_aabb_max_(0), gpu_points_(0), gpu_vind_(0){
|
||||
}
|
||||
~GpuHelper()
|
||||
{
|
||||
delete gpu_splits_;
|
||||
gpu_splits_=0;
|
||||
delete gpu_parent_;
|
||||
gpu_parent_=0;
|
||||
delete gpu_child1_;
|
||||
gpu_child1_=0;
|
||||
delete gpu_aabb_max_;
|
||||
gpu_aabb_max_=0;
|
||||
delete gpu_aabb_min_;
|
||||
gpu_aabb_min_=0;
|
||||
delete gpu_vind_;
|
||||
gpu_vind_=0;
|
||||
|
||||
delete gpu_points_;
|
||||
gpu_points_=0;
|
||||
}
|
||||
};
|
||||
|
||||
//! thrust transform functor
|
||||
//! transforms indices in the internal data set back to the original indices
|
||||
struct map_indices
|
||||
{
|
||||
const int* v_;
|
||||
|
||||
map_indices(const int* v) : v_(v) {
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
float operator() (const int&i) const
|
||||
{
|
||||
if( i>= 0 ) return v_[i];
|
||||
else return i;
|
||||
}
|
||||
};
|
||||
|
||||
//! implementation of L2 distance for the CUDA kernels
|
||||
struct CudaL2
|
||||
{
|
||||
|
||||
static float
|
||||
__host__ __device__
|
||||
axisDist( float a, float b )
|
||||
{
|
||||
return (a-b)*(a-b);
|
||||
}
|
||||
|
||||
static float
|
||||
__host__ __device__
|
||||
dist( float4 a, float4 b )
|
||||
{
|
||||
float4 diff = a-b;
|
||||
return dot(diff,diff);
|
||||
}
|
||||
};
|
||||
|
||||
//! implementation of L1 distance for the CUDA kernels
|
||||
//! NOT TESTED!
|
||||
struct CudaL1
|
||||
{
|
||||
|
||||
static float
|
||||
__host__ __device__
|
||||
axisDist( float a, float b )
|
||||
{
|
||||
return fabs(a-b);
|
||||
}
|
||||
|
||||
static float
|
||||
__host__ __device__
|
||||
dist( float4 a, float4 b )
|
||||
{
|
||||
return fabs(a.x-b.x)+fabs (a.y-b.y)+( a.z-b.z)+(a.w-b.w);
|
||||
}
|
||||
};
|
||||
|
||||
//! used to adapt CPU and GPU distance types.
|
||||
//! specializations define the ::type as their corresponding GPU distance type
|
||||
//! \see GpuDistance< L2<float> >, GpuDistance< L2_Simple<float> >
|
||||
template< class Distance >
|
||||
struct GpuDistance
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct GpuDistance< L2<float> >
|
||||
{
|
||||
typedef CudaL2 type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct GpuDistance< L2_Simple<float> >
|
||||
{
|
||||
typedef CudaL2 type;
|
||||
};
|
||||
template<>
|
||||
struct GpuDistance< L1<float> >
|
||||
{
|
||||
typedef CudaL1 type;
|
||||
};
|
||||
|
||||
|
||||
template< typename Distance >
|
||||
void KDTreeCuda3dIndex<Distance>::knnSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, size_t knn, const SearchParams& params) const
|
||||
{
|
||||
assert(indices.rows >= queries.rows);
|
||||
assert(dists.rows >= queries.rows);
|
||||
assert(int(indices.cols) >= knn);
|
||||
assert( dists.cols == indices.cols && dists.stride==indices.stride );
|
||||
|
||||
int istride=queries.stride/sizeof(ElementType);
|
||||
int ostride=indices.stride/4;
|
||||
|
||||
bool matrices_on_gpu = params.matrices_in_gpu_ram;
|
||||
|
||||
int threadsPerBlock = 128;
|
||||
int blocksPerGrid=(queries.rows+threadsPerBlock-1)/threadsPerBlock;
|
||||
|
||||
float epsError = 1+params.eps;
|
||||
bool sorted = params.sorted;
|
||||
bool use_heap = params.use_heap;
|
||||
|
||||
typename GpuDistance<Distance>::type distance;
|
||||
// std::cout<<" search: "<<std::endl;
|
||||
// std::cout<<" rows: "<<indices.rows<<" "<<dists.rows<<" "<<queries.rows<<std::endl;
|
||||
// std::cout<<" cols: "<<indices.cols<<" "<<dists.cols<<" "<<queries.cols<<std::endl;
|
||||
// std::cout<<" stride: "<<indices.stride<<" "<<dists.stride<<" "<<queries.stride<<std::endl;
|
||||
// std::cout<<" stride2:"<<istride<<" "<<ostride<<std::endl;
|
||||
// std::cout<<" knn:"<<knn<<" matrices_on_gpu:"<<matrices_on_gpu<<std::endl;
|
||||
|
||||
if( !matrices_on_gpu ) {
|
||||
thrust::device_vector<float> queriesDev(istride* queries.rows,0);
|
||||
thrust::copy( queries.ptr(), queries.ptr()+istride*queries.rows, queriesDev.begin() );
|
||||
thrust::device_vector<float> distsDev(queries.rows* ostride);
|
||||
thrust::device_vector<int> indicesDev(queries.rows* ostride);
|
||||
|
||||
|
||||
|
||||
if( knn==1 ) {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
istride,
|
||||
ostride,
|
||||
thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
thrust::raw_pointer_cast(&distsDev[0]),
|
||||
queries.rows, flann::cuda::SingleResultSet<float>(epsError),distance);
|
||||
// KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_nodes_)[0])),
|
||||
// thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
// thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
// queries.stride,
|
||||
// thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
// thrust::raw_pointer_cast(&distsDev[0]),
|
||||
// queries.rows, epsError);
|
||||
//
|
||||
}
|
||||
else {
|
||||
if( use_heap ) {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
istride,
|
||||
ostride,
|
||||
thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
thrust::raw_pointer_cast(&distsDev[0]),
|
||||
queries.rows, flann::cuda::KnnResultSet<float, true>(knn,sorted,epsError)
|
||||
, distance);
|
||||
}
|
||||
else {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
istride,
|
||||
ostride,
|
||||
thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
thrust::raw_pointer_cast(&distsDev[0]),
|
||||
queries.rows, flann::cuda::KnnResultSet<float, false>(knn,sorted,epsError),
|
||||
distance
|
||||
);
|
||||
}
|
||||
}
|
||||
thrust::copy( distsDev.begin(), distsDev.end(), dists.ptr() );
|
||||
thrust::transform(indicesDev.begin(), indicesDev.end(), indicesDev.begin(), map_indices(thrust::raw_pointer_cast( &((*gpu_helper_->gpu_vind_))[0]) ));
|
||||
thrust::copy( indicesDev.begin(), indicesDev.end(), indices.ptr() );
|
||||
}
|
||||
else {
|
||||
thrust::device_ptr<float> qd = thrust::device_pointer_cast(queries.ptr());
|
||||
thrust::device_ptr<float> dd = thrust::device_pointer_cast(dists.ptr());
|
||||
thrust::device_ptr<int> id = thrust::device_pointer_cast(indices.ptr());
|
||||
|
||||
|
||||
|
||||
if( knn==1 ) {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
qd.get(),
|
||||
istride,
|
||||
ostride,
|
||||
id.get(),
|
||||
dd.get(),
|
||||
queries.rows, flann::cuda::SingleResultSet<float>(epsError),distance);
|
||||
// KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_nodes_)[0])),
|
||||
// thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
// thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
// queries.stride,
|
||||
// thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
// thrust::raw_pointer_cast(&distsDev[0]),
|
||||
// queries.rows, epsError);
|
||||
//
|
||||
}
|
||||
else {
|
||||
if( use_heap ) {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
qd.get(),
|
||||
istride,
|
||||
ostride,
|
||||
id.get(),
|
||||
dd.get(),
|
||||
queries.rows, flann::cuda::KnnResultSet<float, true>(knn,sorted,epsError)
|
||||
, distance);
|
||||
}
|
||||
else {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
qd.get(),
|
||||
istride,
|
||||
ostride,
|
||||
id.get(),
|
||||
dd.get(),
|
||||
queries.rows, flann::cuda::KnnResultSet<float, false>(knn,sorted,epsError),
|
||||
distance
|
||||
);
|
||||
}
|
||||
}
|
||||
thrust::transform(id, id+knn*queries.rows, id, map_indices(thrust::raw_pointer_cast( &((*gpu_helper_->gpu_vind_))[0]) ));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template< typename Distance>
|
||||
int KDTreeCuda3dIndex<Distance >::radiusSearchGpu(const Matrix<ElementType>& queries, std::vector< std::vector<int> >& indices,
|
||||
std::vector<std::vector<DistanceType> >& dists, float radius, const SearchParams& params) const
|
||||
{
|
||||
// assert(indices.roasdfws >= queries.rows);
|
||||
// assert(dists.rows >= queries.rows);
|
||||
|
||||
int max_neighbors = params.max_neighbors;
|
||||
bool sorted = params.sorted;
|
||||
bool use_heap = params.use_heap;
|
||||
if (indices.size() < queries.rows ) indices.resize(queries.rows);
|
||||
if (dists.size() < queries.rows ) dists.resize(queries.rows);
|
||||
|
||||
int istride=queries.stride/sizeof(ElementType);
|
||||
|
||||
thrust::device_vector<float> queriesDev(istride* queries.rows,0);
|
||||
thrust::copy( queries.ptr(), queries.ptr()+istride*queries.rows, queriesDev.begin() );
|
||||
thrust::device_vector<int> countsDev(queries.rows);
|
||||
|
||||
typename GpuDistance<Distance>::type distance;
|
||||
|
||||
int threadsPerBlock = 128;
|
||||
int blocksPerGrid=(queries.rows+threadsPerBlock-1)/threadsPerBlock;
|
||||
|
||||
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
istride,
|
||||
1,
|
||||
thrust::raw_pointer_cast(&countsDev[0]),
|
||||
0,
|
||||
queries.rows, flann::cuda::CountingRadiusResultSet<float>(radius,max_neighbors),
|
||||
distance
|
||||
);
|
||||
|
||||
thrust::host_vector<int> counts_host=countsDev;
|
||||
|
||||
if( max_neighbors!=0 ) { // we'll need this later, but the exclusive_scan will change the array
|
||||
for( size_t i=0; i<queries.rows; i++ ) {
|
||||
int count = counts_host[i];
|
||||
if( count > 0 ) {
|
||||
indices[i].resize(count);
|
||||
dists[i].resize(count);
|
||||
}
|
||||
else {
|
||||
indices[i].clear();
|
||||
dists[i].clear();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int neighbors_last_elem = countsDev.back();
|
||||
thrust::exclusive_scan( countsDev.begin(), countsDev.end(), countsDev.begin() );
|
||||
|
||||
size_t total_neighbors=neighbors_last_elem+countsDev.back();
|
||||
if( max_neighbors==0 ) return total_neighbors;
|
||||
|
||||
thrust::device_vector<int> indicesDev(total_neighbors,-1);
|
||||
thrust::device_vector<float> distsDev(total_neighbors,std::numeric_limits<float>::infinity());
|
||||
|
||||
if( max_neighbors<0 ) {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
istride,
|
||||
1,
|
||||
thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
thrust::raw_pointer_cast(&distsDev[0]),
|
||||
queries.rows, flann::cuda::RadiusResultSet<float>(radius,thrust::raw_pointer_cast(&countsDev[0]),sorted), distance);
|
||||
}
|
||||
else {
|
||||
if( use_heap ) {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
istride,
|
||||
1,
|
||||
thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
thrust::raw_pointer_cast(&distsDev[0]),
|
||||
queries.rows, flann::cuda::RadiusKnnResultSet<float, true>(radius,max_neighbors, thrust::raw_pointer_cast(&countsDev[0]),sorted), distance);
|
||||
}
|
||||
else {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
istride,
|
||||
1,
|
||||
thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
thrust::raw_pointer_cast(&distsDev[0]),
|
||||
queries.rows, flann::cuda::RadiusKnnResultSet<float, false>(radius,max_neighbors, thrust::raw_pointer_cast(&countsDev[0]),sorted), distance);
|
||||
}
|
||||
}
|
||||
thrust::transform(indicesDev.begin(), indicesDev.end(), indicesDev.begin(), map_indices(thrust::raw_pointer_cast( &((*gpu_helper_->gpu_vind_))[0]) ));
|
||||
thrust::host_vector<int> indices_temp = indicesDev;
|
||||
thrust::host_vector<float> dists_temp = distsDev;
|
||||
|
||||
int buffer_index=0;
|
||||
for( size_t i=0; i<queries.rows; i++ ) {
|
||||
for( size_t j=0; j<counts_host[i]; j++ ) {
|
||||
dists[i][j]=dists_temp[buffer_index];
|
||||
indices[i][j]=indices_temp[buffer_index];
|
||||
++buffer_index;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer_index;
|
||||
}
|
||||
|
||||
//! used in the radius search to count the total number of neighbors
|
||||
struct isNotMinusOne
|
||||
{
|
||||
__host__ __device__
|
||||
bool operator() ( int i ){
|
||||
return i!=-1;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Distance>
|
||||
int KDTreeCuda3dIndex< Distance >::radiusSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, float radius, const SearchParams& params) const
|
||||
{
|
||||
int max_neighbors = params.max_neighbors;
|
||||
assert(indices.rows >= queries.rows);
|
||||
assert(dists.rows >= queries.rows || max_neighbors==0 );
|
||||
assert(indices.stride==dists.stride || max_neighbors==0 );
|
||||
assert( indices.cols==indices.stride/sizeof(int) );
|
||||
assert(dists.rows >= queries.rows || max_neighbors==0 );
|
||||
|
||||
bool sorted = params.sorted;
|
||||
bool matrices_on_gpu = params.matrices_in_gpu_ram;
|
||||
float epsError = 1+params.eps;
|
||||
bool use_heap = params.use_heap;
|
||||
int istride=queries.stride/sizeof(ElementType);
|
||||
int ostride= indices.stride/4;
|
||||
|
||||
|
||||
if( max_neighbors<0 ) max_neighbors=indices.cols;
|
||||
|
||||
if( !matrices_on_gpu ) {
|
||||
thrust::device_vector<float> queriesDev(istride* queries.rows,0);
|
||||
thrust::copy( queries.ptr(), queries.ptr()+istride*queries.rows, queriesDev.begin() );
|
||||
typename GpuDistance<Distance>::type distance;
|
||||
int threadsPerBlock = 128;
|
||||
int blocksPerGrid=(queries.rows+threadsPerBlock-1)/threadsPerBlock;
|
||||
if( max_neighbors== 0 ) {
|
||||
thrust::device_vector<int> indicesDev(queries.rows* ostride);
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
istride,
|
||||
ostride,
|
||||
thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
0,
|
||||
queries.rows, flann::cuda::CountingRadiusResultSet<float>(radius,-1),
|
||||
distance
|
||||
);
|
||||
thrust::copy( indicesDev.begin(), indicesDev.end(), indices.ptr() );
|
||||
return thrust::reduce(indicesDev.begin(), indicesDev.end() );
|
||||
}
|
||||
|
||||
|
||||
thrust::device_vector<float> distsDev(queries.rows* max_neighbors);
|
||||
thrust::device_vector<int> indicesDev(queries.rows* max_neighbors);
|
||||
|
||||
if( use_heap ) {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
istride,
|
||||
ostride,
|
||||
thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
thrust::raw_pointer_cast(&distsDev[0]),
|
||||
queries.rows, flann::cuda::KnnRadiusResultSet<float, true>(max_neighbors,sorted,epsError, radius), distance);
|
||||
}
|
||||
else {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
thrust::raw_pointer_cast(&queriesDev[0]),
|
||||
istride,
|
||||
ostride,
|
||||
thrust::raw_pointer_cast(&indicesDev[0]),
|
||||
thrust::raw_pointer_cast(&distsDev[0]),
|
||||
queries.rows, flann::cuda::KnnRadiusResultSet<float, false>(max_neighbors,sorted,epsError, radius), distance);
|
||||
}
|
||||
|
||||
thrust::copy( distsDev.begin(), distsDev.end(), dists.ptr() );
|
||||
thrust::transform(indicesDev.begin(), indicesDev.end(), indicesDev.begin(), map_indices(thrust::raw_pointer_cast( &((*gpu_helper_->gpu_vind_))[0]) ));
|
||||
thrust::copy( indicesDev.begin(), indicesDev.end(), indices.ptr() );
|
||||
|
||||
return thrust::count_if(indicesDev.begin(), indicesDev.end(), isNotMinusOne() );
|
||||
}
|
||||
else {
|
||||
|
||||
thrust::device_ptr<float> qd=thrust::device_pointer_cast(queries.ptr());
|
||||
thrust::device_ptr<float> dd=thrust::device_pointer_cast(dists.ptr());
|
||||
thrust::device_ptr<int> id=thrust::device_pointer_cast(indices.ptr());
|
||||
typename GpuDistance<Distance>::type distance;
|
||||
int threadsPerBlock = 128;
|
||||
int blocksPerGrid=(queries.rows+threadsPerBlock-1)/threadsPerBlock;
|
||||
|
||||
if( max_neighbors== 0 ) {
|
||||
thrust::device_vector<int> indicesDev(queries.rows* indices.stride);
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
qd.get(),
|
||||
istride,
|
||||
ostride,
|
||||
id.get(),
|
||||
0,
|
||||
queries.rows, flann::cuda::CountingRadiusResultSet<float>(radius,-1),
|
||||
distance
|
||||
);
|
||||
thrust::copy( indicesDev.begin(), indicesDev.end(), indices.ptr() );
|
||||
return thrust::reduce(indicesDev.begin(), indicesDev.end() );
|
||||
}
|
||||
|
||||
if( use_heap ) {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
qd.get(),
|
||||
istride,
|
||||
ostride,
|
||||
id.get(),
|
||||
dd.get(),
|
||||
queries.rows, flann::cuda::KnnRadiusResultSet<float, true>(max_neighbors,sorted,epsError, radius), distance);
|
||||
}
|
||||
else {
|
||||
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_child1_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_parent_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_min_)[0])),
|
||||
thrust::raw_pointer_cast(&((*gpu_helper_->gpu_aabb_max_)[0])),
|
||||
thrust::raw_pointer_cast( &((*gpu_helper_->gpu_points_)[0]) ),
|
||||
qd.get(),
|
||||
istride,
|
||||
ostride,
|
||||
id.get(),
|
||||
dd.get(),
|
||||
queries.rows, flann::cuda::KnnRadiusResultSet<float, false>(max_neighbors,sorted,epsError, radius), distance);
|
||||
}
|
||||
|
||||
thrust::transform(id, id+max_neighbors*queries.rows, id, map_indices(thrust::raw_pointer_cast( &((*gpu_helper_->gpu_vind_))[0]) ));
|
||||
|
||||
return thrust::count_if(id, id+max_neighbors*queries.rows, isNotMinusOne() );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Distance>
|
||||
void KDTreeCuda3dIndex<Distance>::uploadTreeToGpu()
|
||||
{
|
||||
// just make sure that no weird alignment stuff is going on...
|
||||
// shouldn't, but who knows
|
||||
// (I would make this a (boost) static assertion, but so far flann seems to avoid boost
|
||||
// assert( sizeof( KdTreeCudaPrivate::GpuNode)==sizeof( Node ) );
|
||||
delete gpu_helper_;
|
||||
gpu_helper_ = new GpuHelper;
|
||||
gpu_helper_->gpu_points_=new thrust::device_vector<float4>(size_);
|
||||
thrust::device_vector<float4> tmp(size_);
|
||||
if( get_param(index_params_,"input_is_gpu_float4",false) ) {
|
||||
assert( dataset_.cols == 3 && dataset_.stride==4*sizeof(float));
|
||||
thrust::copy( thrust::device_pointer_cast((float4*)dataset_.ptr()),thrust::device_pointer_cast((float4*)(dataset_.ptr()))+size_,tmp.begin());
|
||||
|
||||
}
|
||||
else {
|
||||
// k is limited to 4 -> use 128bit-alignment regardless of dimensionality
|
||||
// makes cpu search about 5% slower, but gpu can read a float4 w/ a single instruction
|
||||
// (vs a float2 and a float load for a float3 value)
|
||||
// pad data directly to avoid having to copy and re-format the data when
|
||||
// copying it to the GPU
|
||||
data_ = flann::Matrix<ElementType>(new ElementType[size_*4], size_, dim_,4*4);
|
||||
for (size_t i=0; i<size_; ++i) {
|
||||
for (size_t j=0; j<dim_; ++j) {
|
||||
data_[i][j] = dataset_[i][j];
|
||||
}
|
||||
for (size_t j=dim_; j<4; ++j) {
|
||||
data_[i][j] = 0;
|
||||
}
|
||||
}
|
||||
thrust::copy((float4*)data_.ptr(),(float4*)(data_.ptr())+size_,tmp.begin());
|
||||
}
|
||||
|
||||
CudaKdTreeBuilder builder( tmp, leaf_max_size_ );
|
||||
builder.buildTree();
|
||||
|
||||
gpu_helper_->gpu_splits_ = builder.splits_;
|
||||
gpu_helper_->gpu_aabb_min_ = builder.aabb_min_;
|
||||
gpu_helper_->gpu_aabb_max_ = builder.aabb_max_;
|
||||
gpu_helper_->gpu_child1_ = builder.child1_;
|
||||
gpu_helper_->gpu_parent_=builder.parent_;
|
||||
gpu_helper_->gpu_vind_=builder.index_x_;
|
||||
thrust::gather( builder.index_x_->begin(), builder.index_x_->end(), tmp.begin(), gpu_helper_->gpu_points_->begin());
|
||||
|
||||
// gpu_helper_->gpu_nodes_=new thrust::device_vector<KdTreeCudaPrivate::GpuNode>(node_count_);
|
||||
|
||||
|
||||
// gpu_helper_->gpu_vind_=new thrust::device_vector<int>(size_);
|
||||
// thrust::copy( (KdTreeCudaPrivate::GpuNode*)&(tree_[0]), ((KdTreeCudaPrivate::GpuNode*)&(tree_[0]))+tree_.size(), gpu_helper_->gpu_nodes_->begin());
|
||||
|
||||
// thrust::copy(vind_.begin(),vind_.end(),gpu_helper_->gpu_vind_->begin());
|
||||
|
||||
// buildGpuTree();
|
||||
}
|
||||
|
||||
|
||||
template<typename Distance>
|
||||
void KDTreeCuda3dIndex<Distance>::clearGpuBuffers()
|
||||
{
|
||||
delete gpu_helper_;
|
||||
gpu_helper_=0;
|
||||
}
|
||||
|
||||
// explicit instantiations for distance-independent functions
|
||||
template
|
||||
void KDTreeCuda3dIndex<flann::L2<float> >::uploadTreeToGpu();
|
||||
|
||||
template
|
||||
void KDTreeCuda3dIndex<flann::L2<float> >::clearGpuBuffers();
|
||||
|
||||
template
|
||||
struct KDTreeCuda3dIndex<flann::L2<float> >::GpuHelper;
|
||||
|
||||
template
|
||||
void KDTreeCuda3dIndex<flann::L2<float> >::knnSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, size_t knn, const SearchParams& params) const;
|
||||
|
||||
template
|
||||
int KDTreeCuda3dIndex< flann::L2<float> >::radiusSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, float radius, const SearchParams& params) const;
|
||||
template
|
||||
int KDTreeCuda3dIndex< flann::L2<float> >::radiusSearchGpu(const Matrix<ElementType>& queries, std::vector< std::vector<int> >& indices,
|
||||
std::vector<std::vector<DistanceType> >& dists, float radius, const SearchParams& params) const;
|
||||
|
||||
// explicit instantiations for distance-independent functions
|
||||
template
|
||||
void KDTreeCuda3dIndex<flann::L2_Simple<float> >::uploadTreeToGpu();
|
||||
|
||||
template
|
||||
void KDTreeCuda3dIndex<flann::L2_Simple<float> >::clearGpuBuffers();
|
||||
|
||||
template
|
||||
struct KDTreeCuda3dIndex<flann::L2_Simple<float> >::GpuHelper;
|
||||
|
||||
template
|
||||
void KDTreeCuda3dIndex<flann::L2_Simple<float> >::knnSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, size_t knn, const SearchParams& params) const;
|
||||
|
||||
template
|
||||
int KDTreeCuda3dIndex< flann::L2_Simple<float> >::radiusSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, float radius, const SearchParams& params) const;
|
||||
template
|
||||
int KDTreeCuda3dIndex< flann::L2_Simple<float> >::radiusSearchGpu(const Matrix<ElementType>& queries, std::vector< std::vector<int> >& indices,
|
||||
std::vector<std::vector<DistanceType> >& dists, float radius, const SearchParams& params) const;
|
||||
|
||||
|
||||
// explicit instantiations for distance-independent functions
|
||||
template
|
||||
void KDTreeCuda3dIndex<flann::L1<float> >::uploadTreeToGpu();
|
||||
|
||||
template
|
||||
void KDTreeCuda3dIndex<flann::L1<float> >::clearGpuBuffers();
|
||||
|
||||
template
|
||||
struct KDTreeCuda3dIndex<flann::L1<float> >::GpuHelper;
|
||||
|
||||
template
|
||||
void KDTreeCuda3dIndex<flann::L1<float> >::knnSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, size_t knn, const SearchParams& params) const;
|
||||
|
||||
template
|
||||
int KDTreeCuda3dIndex< flann::L1<float> >::radiusSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, float radius, const SearchParams& params) const;
|
||||
template
|
||||
int KDTreeCuda3dIndex< flann::L1<float> >::radiusSearchGpu(const Matrix<ElementType>& queries, std::vector< std::vector<int> >& indices,
|
||||
std::vector<std::vector<DistanceType> >& dists, float radius, const SearchParams& params) const;
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja ([email protected]). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe ([email protected]). All rights reserved.
|
||||
* Copyright 2011 Andreas Muetzel ([email protected]). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_KDTREE_CUDA_3D_INDEX_H_
|
||||
#define FLANN_KDTREE_CUDA_3D_INDEX_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include "flann/general.h"
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "flann/util/matrix.h"
|
||||
#include "flann/util/result_set.h"
|
||||
#include "flann/util/heap.h"
|
||||
#include "flann/util/allocator.h"
|
||||
#include "flann/util/random.h"
|
||||
#include "flann/util/saving.h"
|
||||
#include "flann/util/params.h"
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
struct KDTreeCuda3dIndexParams : public IndexParams
|
||||
{
|
||||
KDTreeCuda3dIndexParams( int leaf_max_size = 64 )
|
||||
{
|
||||
(*this)["algorithm"] = FLANN_INDEX_KDTREE_CUDA;
|
||||
(*this)["leaf_max_size"] = leaf_max_size;
|
||||
(*this)["dim"] = 3;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cuda KD Tree.
|
||||
* Tree is built with GPU assistance and search is performed on the GPU, too.
|
||||
*
|
||||
* Usually faster than the CPU search for data (and query) sets larger than 250000-300000 points, depending
|
||||
* on your CPU and GPU.
|
||||
*/
|
||||
template <typename Distance>
|
||||
class KDTreeCuda3dIndex : public NNIndex<Distance>
|
||||
{
|
||||
public:
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
typedef NNIndex<Distance> BaseClass;
|
||||
|
||||
int visited_leafs;
|
||||
|
||||
typedef bool needs_kdtree_distance;
|
||||
|
||||
/**
|
||||
* KDTree constructor
|
||||
*
|
||||
* Params:
|
||||
* inputData = dataset with the input features
|
||||
* params = parameters passed to the kdtree algorithm
|
||||
*/
|
||||
KDTreeCuda3dIndex(const Matrix<ElementType>& inputData, const IndexParams& params = KDTreeCuda3dIndexParams(),
|
||||
Distance d = Distance() ) : BaseClass(params,d), dataset_(inputData), leaf_count_(0), visited_leafs(0), node_count_(0), current_node_count_(0)
|
||||
{
|
||||
size_ = dataset_.rows;
|
||||
dim_ = dataset_.cols;
|
||||
|
||||
int dim_param = get_param(params,"dim",-1);
|
||||
if (dim_param>0) dim_ = dim_param;
|
||||
leaf_max_size_ = get_param(params,"leaf_max_size",10);
|
||||
assert( dim_ == 3 );
|
||||
gpu_helper_=0;
|
||||
}
|
||||
|
||||
KDTreeCuda3dIndex(const KDTreeCuda3dIndex& other);
|
||||
KDTreeCuda3dIndex operator=(KDTreeCuda3dIndex other);
|
||||
|
||||
/**
|
||||
* Standard destructor
|
||||
*/
|
||||
~KDTreeCuda3dIndex()
|
||||
{
|
||||
delete[] data_.ptr();
|
||||
clearGpuBuffers();
|
||||
}
|
||||
|
||||
BaseClass* clone() const
|
||||
{
|
||||
throw FLANNException("KDTreeCuda3dIndex cloning is not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the index
|
||||
*/
|
||||
void buildIndex()
|
||||
{
|
||||
// Create a permutable array of indices to the input vectors.
|
||||
vind_.resize(size_);
|
||||
for (size_t i = 0; i < size_; i++) {
|
||||
vind_[i] = i;
|
||||
}
|
||||
|
||||
leaf_count_=0;
|
||||
node_count_=0;
|
||||
// computeBoundingBox(root_bbox_);
|
||||
// tree_.reserve(log2((double)size_/leaf_max_size_));
|
||||
// divideTree(0, size_, root_bbox_,-1 ); // construct the tree
|
||||
|
||||
delete[] data_.ptr();
|
||||
|
||||
uploadTreeToGpu();
|
||||
}
|
||||
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return FLANN_INDEX_KDTREE_SINGLE;
|
||||
}
|
||||
|
||||
|
||||
void removePoint(size_t index)
|
||||
{
|
||||
throw FLANNException( "removePoint not implemented for this index type!" );
|
||||
}
|
||||
|
||||
ElementType* getPoint(size_t id)
|
||||
{
|
||||
return dataset_[id];
|
||||
}
|
||||
|
||||
void saveIndex(FILE* stream)
|
||||
{
|
||||
throw FLANNException( "Index saving not implemented!" );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loadIndex(FILE* stream)
|
||||
{
|
||||
throw FLANNException( "Index loading not implemented!" );
|
||||
}
|
||||
|
||||
size_t veclen() const
|
||||
{
|
||||
return dim_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the inde memory usage
|
||||
* Returns: memory used by the index
|
||||
* TODO: return system or gpu RAM or both?
|
||||
*/
|
||||
int usedMemory() const
|
||||
{
|
||||
// return tree_.size()*sizeof(Node)+dataset_.rows*sizeof(int); // pool memory and vind array memory
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Perform k-nearest neighbor search
|
||||
* \param[in] queries The query points for which to find the nearest neighbors
|
||||
* \param[out] indices The indices of the nearest neighbors found
|
||||
* \param[out] dists Distances to the nearest neighbors found
|
||||
* \param[in] knn Number of nearest neighbors to return
|
||||
* \param[in] params Search parameters
|
||||
*/
|
||||
int knnSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, size_t knn, const SearchParams& params) const
|
||||
{
|
||||
knnSearchGpu(queries,indices, dists, knn, params);
|
||||
return knn*queries.rows; // hack...
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Perform k-nearest neighbor search
|
||||
* \param[in] queries The query points for which to find the nearest neighbors
|
||||
* \param[out] indices The indices of the nearest neighbors found
|
||||
* \param[out] dists Distances to the nearest neighbors found
|
||||
* \param[in] knn Number of nearest neighbors to return
|
||||
* \param[in] params Search parameters
|
||||
*/
|
||||
int knnSearch(const Matrix<ElementType>& queries,
|
||||
std::vector< std::vector<int> >& indices,
|
||||
std::vector<std::vector<DistanceType> >& dists,
|
||||
size_t knn,
|
||||
const SearchParams& params) const
|
||||
{
|
||||
knnSearchGpu(queries,indices, dists, knn, params);
|
||||
return knn*queries.rows; // hack...
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Perform k-nearest neighbor search
|
||||
* \param[in] queries The query points for which to find the nearest neighbors
|
||||
* \param[out] indices The indices of the nearest neighbors found
|
||||
* \param[out] dists Distances to the nearest neighbors found
|
||||
* \param[in] knn Number of nearest neighbors to return
|
||||
* \param[in] params Search parameters
|
||||
*/
|
||||
void knnSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, size_t knn, const SearchParams& params) const;
|
||||
|
||||
int knnSearchGpu(const Matrix<ElementType>& queries,
|
||||
std::vector< std::vector<int> >& indices,
|
||||
std::vector<std::vector<DistanceType> >& dists,
|
||||
size_t knn,
|
||||
const SearchParams& params) const
|
||||
{
|
||||
flann::Matrix<int> ind( new int[knn*queries.rows], queries.rows,knn);
|
||||
flann::Matrix<DistanceType> dist( new DistanceType[knn*queries.rows], queries.rows,knn);
|
||||
knnSearchGpu(queries,ind,dist,knn,params);
|
||||
for( size_t i = 0; i<queries.rows; i++ ) {
|
||||
indices[i].resize(knn);
|
||||
dists[i].resize(knn);
|
||||
for( size_t j=0; j<knn; j++ ) {
|
||||
indices[i][j]=ind[i][j];
|
||||
dists[i][j]=dist[i][j];
|
||||
}
|
||||
}
|
||||
delete [] ind.ptr();
|
||||
delete [] dist.ptr();
|
||||
return knn*queries.rows; // hack...
|
||||
}
|
||||
|
||||
int radiusSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists,
|
||||
float radius, const SearchParams& params) const
|
||||
{
|
||||
return radiusSearchGpu(queries,indices, dists, radius, params);
|
||||
}
|
||||
|
||||
int radiusSearch(const Matrix<ElementType>& queries, std::vector< std::vector<int> >& indices,
|
||||
std::vector<std::vector<DistanceType> >& dists, float radius, const SearchParams& params) const
|
||||
{
|
||||
return radiusSearchGpu(queries,indices, dists, radius, params);
|
||||
}
|
||||
|
||||
int radiusSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists,
|
||||
float radius, const SearchParams& params) const;
|
||||
|
||||
int radiusSearchGpu(const Matrix<ElementType>& queries, std::vector< std::vector<int> >& indices,
|
||||
std::vector<std::vector<DistanceType> >& dists, float radius, const SearchParams& params) const;
|
||||
|
||||
/**
|
||||
* Not implemented, since it is only used by single-element searches.
|
||||
* (but is needed b/c it is abstract in the base class)
|
||||
*/
|
||||
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams) const
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void buildIndexImpl()
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
|
||||
void freeIndex()
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void uploadTreeToGpu( );
|
||||
|
||||
void clearGpuBuffers( );
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
struct GpuHelper;
|
||||
|
||||
GpuHelper* gpu_helper_;
|
||||
|
||||
const Matrix<ElementType> dataset_;
|
||||
|
||||
int leaf_max_size_;
|
||||
|
||||
int leaf_count_;
|
||||
int node_count_;
|
||||
//! used by convertTreeToGpuFormat
|
||||
int current_node_count_;
|
||||
|
||||
|
||||
/**
|
||||
* Array of indices to vectors in the dataset.
|
||||
*/
|
||||
std::vector<int> vind_;
|
||||
|
||||
Matrix<ElementType> data_;
|
||||
|
||||
size_t dim_;
|
||||
|
||||
USING_BASECLASS_SYMBOLS
|
||||
}; // class KDTreeCuda3dIndex
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //FLANN_KDTREE_SINGLE_INDEX_H_
|
||||
@@ -1,729 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2011 Andreas Muetzel ([email protected]). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_CUDA_KD_TREE_BUILDER_H_
|
||||
#define FLANN_CUDA_KD_TREE_BUILDER_H_
|
||||
#include <thrust/host_vector.h>
|
||||
#include <thrust/device_vector.h>
|
||||
#include <thrust/sort.h>
|
||||
#include <thrust/partition.h>
|
||||
#include <thrust/unique.h>
|
||||
#include <thrust/scan.h>
|
||||
#include <flann/util/cutil_math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// #define PRINT_DEBUG_TIMING
|
||||
|
||||
namespace flann
|
||||
{
|
||||
// template< typename T >
|
||||
// void print_vector( const thrust::device_vector<T>& v )
|
||||
// {
|
||||
// for( int i=0; i< v.size(); i++ )
|
||||
// {
|
||||
// std::cout<<v[i]<<std::endl;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// template< typename T1, typename T2 >
|
||||
// void print_vector( const thrust::device_vector<T1>& v1, const thrust::device_vector<T2>& v2 )
|
||||
// {
|
||||
// for( int i=0; i< v1.size(); i++ )
|
||||
// {
|
||||
// std::cout<<i<<": "<<v1[i]<<" "<<v2[i]<<std::endl;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// template< typename T1, typename T2, typename T3 >
|
||||
// void print_vector( const thrust::device_vector<T1>& v1, const thrust::device_vector<T2>& v2, const thrust::device_vector<T3>& v3 )
|
||||
// {
|
||||
// for( int i=0; i< v1.size(); i++ )
|
||||
// {
|
||||
// std::cout<<i<<": "<<v1[i]<<" "<<v2[i]<<" "<<v3[i]<<std::endl;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// template< typename T >
|
||||
// void print_vector_by_index( const thrust::device_vector<T>& v,const thrust::device_vector<int>& ind )
|
||||
// {
|
||||
// for( int i=0; i< v.size(); i++ )
|
||||
// {
|
||||
// std::cout<<v[ind[i]]<<std::endl;
|
||||
// }
|
||||
// }
|
||||
|
||||
// std::ostream& operator <<(std::ostream& stream, const cuda::kd_tree_builder_detail::SplitInfo& s) {
|
||||
// stream<<"(split l/r: "<< s.left <<" "<< s.right<< " split:"<<s.split_dim<<" "<<s.split_val<<")";
|
||||
// return stream;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// std::ostream& operator <<(std::ostream& stream, const cuda::kd_tree_builder_detail::NodeInfo& s) {
|
||||
// stream<<"(node: "<<s.child1()<<" "<<s.parent()<<" "<<s.child2()<<")";
|
||||
// return stream;
|
||||
// }
|
||||
//
|
||||
// std::ostream& operator <<(std::ostream& stream, const float4& s) {
|
||||
// stream<<"("<<s.x<<","<<s.y<<","<<s.z<<","<<s.w<<")";
|
||||
// return stream;
|
||||
// }
|
||||
namespace cuda
|
||||
{
|
||||
namespace kd_tree_builder_detail
|
||||
{
|
||||
//! normal node: contains the split dimension and value
|
||||
//! leaf node: left == index of first points, right==index of last point +1
|
||||
struct SplitInfo
|
||||
{
|
||||
union {
|
||||
struct
|
||||
{
|
||||
// begin of child nodes
|
||||
int left;
|
||||
// end of child nodes
|
||||
int right;
|
||||
};
|
||||
struct
|
||||
{
|
||||
int split_dim;
|
||||
float split_val;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
struct IsEven
|
||||
{
|
||||
typedef int result_type;
|
||||
__device__
|
||||
int operator()(int i )
|
||||
{
|
||||
return (i& 1)==0;
|
||||
}
|
||||
};
|
||||
|
||||
struct SecondElementIsEven
|
||||
{
|
||||
__host__ __device__
|
||||
bool operator()( const thrust::tuple<int,int>& i )
|
||||
{
|
||||
return (thrust::get<1>(i)& 1)==0;
|
||||
}
|
||||
};
|
||||
|
||||
//! just for convenience: access a float4 by an index in [0,1,2]
|
||||
//! (casting it to a float* and accessing it by the index is way slower...)
|
||||
__host__ __device__
|
||||
float get_value_by_index( const float4& f, int i )
|
||||
{
|
||||
switch(i) {
|
||||
case 0:
|
||||
return f.x;
|
||||
case 1:
|
||||
return f.y;
|
||||
default:
|
||||
return f.z;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//! mark a point as belonging to the left or right child of its current parent
|
||||
//! called after parents are split
|
||||
struct MovePointsToChildNodes
|
||||
{
|
||||
MovePointsToChildNodes( int* child1, SplitInfo* splits, float* x, float* y, float* z, int* ox, int* oy, int* oz, int* lrx, int* lry, int* lrz )
|
||||
: child1_(child1), splits_(splits), x_(x), y_(y), z_(z), ox_(ox), oy_(oy), oz_(oz), lrx_(lrx), lry_(lry), lrz_(lrz){}
|
||||
// int dim;
|
||||
// float threshold;
|
||||
int* child1_;
|
||||
SplitInfo* splits_;
|
||||
|
||||
// coordinate values
|
||||
float* x_, * y_, * z_;
|
||||
// owner indices -> which node does the point belong to?
|
||||
int* ox_, * oy_, * oz_;
|
||||
// temp info: will be set to 1 of a point is moved to the right child node, 0 otherwise
|
||||
// (used later in the scan op to separate the points of the children into continuous ranges)
|
||||
int* lrx_, * lry_, * lrz_;
|
||||
__device__
|
||||
void operator()( const thrust::tuple<int, int, int, int>& data )
|
||||
{
|
||||
int index = thrust::get<0>(data);
|
||||
int owner = ox_[index]; // before a split, all points at the same position in the index array have the same owner
|
||||
int point_ind1=thrust::get<1>(data);
|
||||
int point_ind2=thrust::get<2>(data);
|
||||
int point_ind3=thrust::get<3>(data);
|
||||
int leftChild=child1_[owner];
|
||||
int split_dim;
|
||||
float dim_val1, dim_val2, dim_val3;
|
||||
SplitInfo split;
|
||||
lrx_[index]=0;
|
||||
lry_[index]=0;
|
||||
lrz_[index]=0;
|
||||
// this element already belongs to a leaf node -> everything alright, no need to change anything
|
||||
if( leftChild==-1 ) {
|
||||
return;
|
||||
}
|
||||
// otherwise: load split data, and assign this index to the new owner
|
||||
split = splits_[owner];
|
||||
split_dim=split.split_dim;
|
||||
switch( split_dim ) {
|
||||
case 0:
|
||||
dim_val1=x_[point_ind1];
|
||||
dim_val2=x_[point_ind2];
|
||||
dim_val3=x_[point_ind3];
|
||||
break;
|
||||
case 1:
|
||||
dim_val1=y_[point_ind1];
|
||||
dim_val2=y_[point_ind2];
|
||||
dim_val3=y_[point_ind3];
|
||||
break;
|
||||
default:
|
||||
dim_val1=z_[point_ind1];
|
||||
dim_val2=z_[point_ind2];
|
||||
dim_val3=z_[point_ind3];
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int r1=leftChild +(dim_val1 > split.split_val);
|
||||
ox_[index]=r1;
|
||||
int r2=leftChild+(dim_val2 > split.split_val);
|
||||
oy_[index]=r2;
|
||||
oz_[index]=leftChild+(dim_val3 > split.split_val);
|
||||
|
||||
lrx_[index] = (dim_val1 > split.split_val);
|
||||
lry_[index] = (dim_val2 > split.split_val);
|
||||
lrz_[index] = (dim_val3 > split.split_val);
|
||||
// return thrust::make_tuple( r1, r2, leftChild+(dim_val > split.split_val) );
|
||||
}
|
||||
};
|
||||
|
||||
//! used to update the left/right pointers and aabb infos after the node splits
|
||||
struct SetLeftAndRightAndAABB
|
||||
{
|
||||
int maxPoints;
|
||||
int nElements;
|
||||
|
||||
SplitInfo* nodes;
|
||||
int* counts;
|
||||
int* labels;
|
||||
float4* aabbMin;
|
||||
float4* aabbMax;
|
||||
const float* x,* y,* z;
|
||||
const int* ix, * iy, * iz;
|
||||
|
||||
__host__ __device__
|
||||
void operator()( int i )
|
||||
{
|
||||
int index=labels[i];
|
||||
int right;
|
||||
int left = counts[i];
|
||||
nodes[index].left=left;
|
||||
if( i < nElements-1 ) {
|
||||
right=counts[i+1];
|
||||
}
|
||||
else { // index==nNodes
|
||||
right=maxPoints;
|
||||
}
|
||||
nodes[index].right=right;
|
||||
aabbMin[index].x=x[ix[left]];
|
||||
aabbMin[index].y=y[iy[left]];
|
||||
aabbMin[index].z=z[iz[left]];
|
||||
aabbMax[index].x=x[ix[right-1]];
|
||||
aabbMax[index].y=y[iy[right-1]];
|
||||
aabbMax[index].z=z[iz[right-1]];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! - decide whether a node has to be split
|
||||
//! if yes:
|
||||
//! - allocate child nodes
|
||||
//! - set split axis as axis of maximum aabb length
|
||||
struct SplitNodes
|
||||
{
|
||||
int maxPointsPerNode;
|
||||
int* node_count;
|
||||
int* nodes_allocated;
|
||||
int* out_of_space;
|
||||
int* child1_;
|
||||
int* parent_;
|
||||
SplitInfo* splits;
|
||||
|
||||
__device__
|
||||
void operator()( thrust::tuple<int&, int&,SplitInfo&,float4&,float4&, int> node ) // float4: aabbMin, aabbMax
|
||||
{
|
||||
int& parent=thrust::get<0>(node);
|
||||
int& child1=thrust::get<1>(node);
|
||||
SplitInfo& s=thrust::get<2>(node);
|
||||
const float4& aabbMin=thrust::get<3>(node);
|
||||
const float4& aabbMax=thrust::get<4>(node);
|
||||
int my_index = thrust::get<5>(node);
|
||||
bool split_node=false;
|
||||
// first, each thread block counts the number of nodes that it needs to allocate...
|
||||
__shared__ int block_nodes_to_allocate;
|
||||
if( threadIdx.x== 0 ) block_nodes_to_allocate=0;
|
||||
__syncthreads();
|
||||
|
||||
// don't split if all points are equal
|
||||
// (could lead to an infinite loop, and doesn't make any sense anyway)
|
||||
bool all_points_in_node_are_equal=aabbMin.x == aabbMax.x && aabbMin.y==aabbMax.y && aabbMin.z==aabbMax.z;
|
||||
|
||||
int offset_to_global=0;
|
||||
|
||||
// maybe this could be replaced with a reduction...
|
||||
if(( child1==-1) &&( s.right-s.left > maxPointsPerNode) && !all_points_in_node_are_equal ) { // leaf node
|
||||
split_node=true;
|
||||
offset_to_global = atomicAdd( &block_nodes_to_allocate,2 );
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
__shared__ int block_left;
|
||||
__shared__ bool enough_space;
|
||||
// ... then the first thread tries to allocate this many nodes...
|
||||
if( threadIdx.x==0) {
|
||||
block_left = atomicAdd( node_count, block_nodes_to_allocate );
|
||||
enough_space = block_left+block_nodes_to_allocate < *nodes_allocated;
|
||||
// if it doesn't succeed, no nodes will be created by this block
|
||||
if( !enough_space ) {
|
||||
atomicAdd( node_count, -block_nodes_to_allocate );
|
||||
*out_of_space=1;
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
// this thread needs to split it's node && there was enough space for all the nodes
|
||||
// in this block.
|
||||
//(The whole "allocate-per-block-thing" is much faster than letting each element allocate
|
||||
// its space on its own, because shared memory atomics are A LOT faster than
|
||||
// global mem atomics!)
|
||||
if( split_node && enough_space ) {
|
||||
int left = block_left + offset_to_global;
|
||||
|
||||
splits[left].left=s.left;
|
||||
splits[left].right=s.right;
|
||||
splits[left+1].left=0;
|
||||
splits[left+1].right=0;
|
||||
|
||||
// split axis/position: middle of longest aabb extent
|
||||
float4 aabbDim=aabbMax-aabbMin;
|
||||
int maxDim=0;
|
||||
float maxDimLength=aabbDim.x;
|
||||
float4 splitVal=(aabbMax+aabbMin);
|
||||
splitVal*=0.5f;
|
||||
for( int i=1; i<=2; i++ ) {
|
||||
float val = get_value_by_index(aabbDim,i);
|
||||
if( val > maxDimLength ) {
|
||||
maxDim=i;
|
||||
maxDimLength=val;
|
||||
}
|
||||
}
|
||||
s.split_dim=maxDim;
|
||||
s.split_val=get_value_by_index(splitVal,maxDim);
|
||||
|
||||
child1_[my_index]=left;
|
||||
splits[my_index]=s;
|
||||
|
||||
parent_[left]=my_index;
|
||||
parent_[left+1]=my_index;
|
||||
child1_[left]=-1;
|
||||
child1_[left+1]=-1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! computes the scatter target address for the split operation, see Sengupta,Harris,Zhang,Owen: Scan Primitives for GPU Computing
|
||||
//! in my use case, this is about 2x as fast as thrust::partition
|
||||
struct set_addr3
|
||||
{
|
||||
const int* val_, * f_;
|
||||
|
||||
int npoints_;
|
||||
__device__
|
||||
int operator()( int id )
|
||||
{
|
||||
int nf = f_[npoints_-1] + (val_[npoints_-1]);
|
||||
int f=f_[id];
|
||||
int t = id -f+nf;
|
||||
return val_[id] ? f : t;
|
||||
}
|
||||
};
|
||||
|
||||
//! converts a float4 point (xyz) to a tuple of three float vals (used to separate the
|
||||
//! float4 input buffer into three arrays in the beginning of the tree build)
|
||||
struct pointxyz_to_px_py_pz
|
||||
{
|
||||
__device__
|
||||
thrust::tuple<float,float,float> operator()( const float4& val )
|
||||
{
|
||||
return thrust::make_tuple(val.x, val.y, val.z);
|
||||
}
|
||||
};
|
||||
} // namespace kd_tree_builder_detail
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
|
||||
std::ostream& operator <<(std::ostream& stream, const cuda::kd_tree_builder_detail::SplitInfo& s)
|
||||
{
|
||||
stream<<"(split l/r: "<< s.left <<" "<< s.right<< " split:"<<s.split_dim<<" "<<s.split_val<<")";
|
||||
return stream;
|
||||
}
|
||||
class CudaKdTreeBuilder
|
||||
{
|
||||
public:
|
||||
CudaKdTreeBuilder( const thrust::device_vector<float4>& points, int max_leaf_size ) : /*out_of_space_(1,0),node_count_(1,1),*/ max_leaf_size_(max_leaf_size)
|
||||
{
|
||||
points_=&points;
|
||||
int prealloc = points.size()/max_leaf_size_*16;
|
||||
allocation_info_.resize(3);
|
||||
allocation_info_[NodeCount]=1;
|
||||
allocation_info_[NodesAllocated]=prealloc;
|
||||
allocation_info_[OutOfSpace]=0;
|
||||
|
||||
// std::cout<<points_->size()<<std::endl;
|
||||
|
||||
child1_=new thrust::device_vector<int>(prealloc,-1);
|
||||
parent_=new thrust::device_vector<int>(prealloc,-1);
|
||||
cuda::kd_tree_builder_detail::SplitInfo s;
|
||||
s.left=0;
|
||||
s.right=0;
|
||||
splits_=new thrust::device_vector<cuda::kd_tree_builder_detail::SplitInfo>(prealloc,s);
|
||||
s.right=points.size();
|
||||
(*splits_)[0]=s;
|
||||
|
||||
aabb_min_=new thrust::device_vector<float4>(prealloc);
|
||||
aabb_max_=new thrust::device_vector<float4>(prealloc);
|
||||
|
||||
index_x_=new thrust::device_vector<int>(points_->size());
|
||||
index_y_=new thrust::device_vector<int>(points_->size());
|
||||
index_z_=new thrust::device_vector<int>(points_->size());
|
||||
|
||||
owners_x_=new thrust::device_vector<int>(points_->size(),0);
|
||||
owners_y_=new thrust::device_vector<int>(points_->size(),0);
|
||||
owners_z_=new thrust::device_vector<int>(points_->size(),0);
|
||||
|
||||
leftright_x_ = new thrust::device_vector<int>(points_->size(),0);
|
||||
leftright_y_ = new thrust::device_vector<int>(points_->size(),0);
|
||||
leftright_z_ = new thrust::device_vector<int>(points_->size(),0);
|
||||
|
||||
tmp_index_=new thrust::device_vector<int>(points_->size());
|
||||
tmp_owners_=new thrust::device_vector<int>(points_->size());
|
||||
tmp_misc_=new thrust::device_vector<int>(points_->size());
|
||||
|
||||
points_x_=new thrust::device_vector<float>(points_->size());
|
||||
points_y_=new thrust::device_vector<float>(points_->size());
|
||||
points_z_=new thrust::device_vector<float>(points_->size());
|
||||
delete_node_info_=false;
|
||||
}
|
||||
|
||||
~CudaKdTreeBuilder()
|
||||
{
|
||||
if( delete_node_info_ ) {
|
||||
delete child1_;
|
||||
delete parent_;
|
||||
delete splits_;
|
||||
delete aabb_min_;
|
||||
delete aabb_max_;
|
||||
delete index_x_;
|
||||
}
|
||||
|
||||
delete index_y_;
|
||||
delete index_z_;
|
||||
delete owners_x_;
|
||||
delete owners_y_;
|
||||
delete owners_z_;
|
||||
delete points_x_;
|
||||
delete points_y_;
|
||||
delete points_z_;
|
||||
delete leftright_x_;
|
||||
delete leftright_y_;
|
||||
delete leftright_z_;
|
||||
delete tmp_index_;
|
||||
delete tmp_owners_;
|
||||
delete tmp_misc_;
|
||||
}
|
||||
|
||||
//! build the tree
|
||||
//! general idea:
|
||||
//! - build sorted lists of the points in x y and z order (to be able to compute tight AABBs in O(1) )
|
||||
//! - while( nodes to split exist )
|
||||
//! - split non-child nodes along longest axis if the number of points is > max_points_per_node
|
||||
//! - for each point: determine whether it is in a node that was split. If yes, mark it as belonging to the left or right child node of its current parent node
|
||||
//! - reorder the points so that the points of a single node are continuous in the node array
|
||||
//! - update the left/right pointers and AABBs of all nodes
|
||||
void buildTree()
|
||||
{
|
||||
// std::cout<<"buildTree()"<<std::endl;
|
||||
// sleep(1);
|
||||
// Util::Timer stepTimer;
|
||||
thrust::transform( points_->begin(), points_->end(), thrust::make_zip_iterator(thrust::make_tuple(points_x_->begin(), points_y_->begin(),points_z_->begin()) ), cuda::kd_tree_builder_detail::pointxyz_to_px_py_pz() );
|
||||
|
||||
thrust::counting_iterator<int> it(0);
|
||||
thrust::copy( it, it+points_->size(), index_x_->begin() );
|
||||
|
||||
thrust::copy( index_x_->begin(), index_x_->end(), index_y_->begin() );
|
||||
thrust::copy( index_x_->begin(), index_x_->end(), index_z_->begin() );
|
||||
|
||||
thrust::device_vector<float> tmpv(points_->size());
|
||||
|
||||
// create sorted index list -> can be used to compute AABBs in O(1)
|
||||
thrust::copy(points_x_->begin(), points_x_->end(), tmpv.begin());
|
||||
thrust::sort_by_key( tmpv.begin(), tmpv.end(), index_x_->begin() );
|
||||
thrust::copy(points_y_->begin(), points_y_->end(), tmpv.begin());
|
||||
thrust::sort_by_key( tmpv.begin(), tmpv.end(), index_y_->begin() );
|
||||
thrust::copy(points_z_->begin(), points_z_->end(), tmpv.begin());
|
||||
thrust::sort_by_key( tmpv.begin(), tmpv.end(), index_z_->begin() );
|
||||
|
||||
|
||||
(*aabb_min_)[0]=make_float4((*points_x_)[(*index_x_)[0]],(*points_y_)[(*index_y_)[0]],(*points_z_)[(*index_z_)[0]],0);
|
||||
|
||||
(*aabb_max_)[0]=make_float4((*points_x_)[(*index_x_)[points_->size()-1]],(*points_y_)[(*index_y_)[points_->size()-1]],(*points_z_)[(*index_z_)[points_->size()-1]],0);
|
||||
#ifdef PRINT_DEBUG_TIMING
|
||||
cudaDeviceSynchronize();
|
||||
std::cout<<" initial stuff:"<<stepTimer.elapsed()<<std::endl;
|
||||
stepTimer.restart();
|
||||
#endif
|
||||
int last_node_count=0;
|
||||
for( int i=0;; i++ ) {
|
||||
cuda::kd_tree_builder_detail::SplitNodes sn;
|
||||
|
||||
sn.maxPointsPerNode=max_leaf_size_;
|
||||
sn.node_count=thrust::raw_pointer_cast(&allocation_info_[NodeCount]);
|
||||
sn.nodes_allocated=thrust::raw_pointer_cast(&allocation_info_[NodesAllocated]);
|
||||
sn.out_of_space=thrust::raw_pointer_cast(&allocation_info_[OutOfSpace]);
|
||||
sn.child1_=thrust::raw_pointer_cast(&(*child1_)[0]);
|
||||
sn.parent_=thrust::raw_pointer_cast(&(*parent_)[0]);
|
||||
sn.splits=thrust::raw_pointer_cast(&(*splits_)[0]);
|
||||
|
||||
thrust::counting_iterator<int> cit(0);
|
||||
thrust::for_each( thrust::make_zip_iterator(thrust::make_tuple( parent_->begin(), child1_->begin(), splits_->begin(), aabb_min_->begin(), aabb_max_->begin(), cit )),
|
||||
thrust::make_zip_iterator(thrust::make_tuple( parent_->begin()+last_node_count, child1_->begin()+last_node_count,splits_->begin()+last_node_count, aabb_min_->begin()+last_node_count, aabb_max_->begin()+last_node_count,cit+last_node_count )),
|
||||
sn );
|
||||
// copy allocation info to host
|
||||
thrust::host_vector<int> alloc_info = allocation_info_;
|
||||
|
||||
if( last_node_count == alloc_info[NodeCount] ) { // no more nodes were split -> done
|
||||
break;
|
||||
}
|
||||
last_node_count=alloc_info[NodeCount];
|
||||
|
||||
// a node was un-splittable due to a lack of space
|
||||
if( alloc_info[OutOfSpace]==1 ) {
|
||||
resize_node_vectors(alloc_info[NodesAllocated]*2);
|
||||
alloc_info[OutOfSpace]=0;
|
||||
alloc_info[NodesAllocated]*=2;
|
||||
allocation_info_=alloc_info;
|
||||
}
|
||||
#ifdef PRINT_DEBUG_TIMING
|
||||
cudaDeviceSynchronize();
|
||||
std::cout<<" node split:"<<stepTimer.elapsed()<<std::endl;
|
||||
stepTimer.restart();
|
||||
#endif
|
||||
|
||||
// foreach point: point was in node that was split?move it to child (leaf) node : do nothing
|
||||
cuda::kd_tree_builder_detail::MovePointsToChildNodes sno( thrust::raw_pointer_cast(&(*child1_)[0]),
|
||||
thrust::raw_pointer_cast(&(*splits_)[0]),
|
||||
thrust::raw_pointer_cast(&(*points_x_)[0]),
|
||||
thrust::raw_pointer_cast(&(*points_y_)[0]),
|
||||
thrust::raw_pointer_cast(&(*points_z_)[0]),
|
||||
thrust::raw_pointer_cast(&(*owners_x_)[0]),
|
||||
thrust::raw_pointer_cast(&(*owners_y_)[0]),
|
||||
thrust::raw_pointer_cast(&(*owners_z_)[0]),
|
||||
thrust::raw_pointer_cast(&(*leftright_x_)[0]),
|
||||
thrust::raw_pointer_cast(&(*leftright_y_)[0]),
|
||||
thrust::raw_pointer_cast(&(*leftright_z_)[0])
|
||||
);
|
||||
thrust::counting_iterator<int> ci0(0);
|
||||
thrust::for_each( thrust::make_zip_iterator( thrust::make_tuple( ci0, index_x_->begin(), index_y_->begin(), index_z_->begin()) ),
|
||||
thrust::make_zip_iterator( thrust::make_tuple( ci0+points_->size(), index_x_->end(), index_y_->end(), index_z_->end()) ),sno );
|
||||
|
||||
#ifdef PRINT_DEBUG_TIMING
|
||||
cudaDeviceSynchronize();
|
||||
std::cout<<" set new owners:"<<stepTimer.elapsed()<<std::endl;
|
||||
stepTimer.restart();
|
||||
#endif
|
||||
|
||||
// move points around so that each leaf node's points are continuous
|
||||
separate_left_and_right_children(*index_x_,*owners_x_,*tmp_index_,*tmp_owners_, *leftright_x_);
|
||||
std::swap(tmp_index_, index_x_);
|
||||
std::swap(tmp_owners_, owners_x_);
|
||||
separate_left_and_right_children(*index_y_,*owners_y_,*tmp_index_,*tmp_owners_, *leftright_y_,false);
|
||||
std::swap(tmp_index_, index_y_);
|
||||
separate_left_and_right_children(*index_z_,*owners_z_,*tmp_index_,*tmp_owners_, *leftright_z_,false);
|
||||
std::swap(tmp_index_, index_z_);
|
||||
|
||||
#ifdef PRINT_DEBUG_TIMING
|
||||
cudaDeviceSynchronize();
|
||||
std::cout<<" split:"<<stepTimer.elapsed()<<std::endl;
|
||||
stepTimer.restart();
|
||||
#endif
|
||||
// calculate new AABB etc
|
||||
update_leftright_and_aabb( *points_x_, *points_y_, *points_z_, *index_x_, *index_y_, *index_z_, *owners_x_, *splits_,*aabb_min_, *aabb_max_);
|
||||
#ifdef PRINT_DEBUG_TIMING
|
||||
cudaDeviceSynchronize();
|
||||
std::cout<<" update_leftright_and_aabb:"<<stepTimer.elapsed()<<std::endl;
|
||||
stepTimer.restart();
|
||||
print_vector(node_count_);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template<class Distance>
|
||||
friend class KDTreeCuda3dIndex;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
//! takes the partitioned nodes, and sets the left-/right info of leaf nodes, as well as the AABBs
|
||||
void
|
||||
update_leftright_and_aabb( const thrust::device_vector<float>& x, const thrust::device_vector<float>& y,const thrust::device_vector<float>& z,
|
||||
const thrust::device_vector<int>& ix, const thrust::device_vector<int>& iy,const thrust::device_vector<int>& iz,
|
||||
const thrust::device_vector<int>& owners,
|
||||
thrust::device_vector<cuda::kd_tree_builder_detail::SplitInfo>& splits, thrust::device_vector<float4>& aabbMin,thrust::device_vector<float4>& aabbMax)
|
||||
{
|
||||
thrust::device_vector<int>* labelsUnique=tmp_owners_;
|
||||
thrust::device_vector<int>* countsUnique=tmp_index_;
|
||||
// assume: points of each node are continuous in the array
|
||||
|
||||
// find which nodes are here, and where each node's points begin and end
|
||||
int unique_labels = thrust::unique_by_key_copy( owners.begin(), owners.end(), thrust::counting_iterator<int>(0), labelsUnique->begin(), countsUnique->begin()).first - labelsUnique->begin();
|
||||
|
||||
// update the info
|
||||
cuda::kd_tree_builder_detail::SetLeftAndRightAndAABB s;
|
||||
s.maxPoints=x.size();
|
||||
s.nElements=unique_labels;
|
||||
s.nodes=thrust::raw_pointer_cast(&(splits[0]));
|
||||
s.counts=thrust::raw_pointer_cast(&( (*countsUnique)[0]));
|
||||
s.labels=thrust::raw_pointer_cast(&( (*labelsUnique)[0]));
|
||||
s.x=thrust::raw_pointer_cast(&x[0]);
|
||||
s.y=thrust::raw_pointer_cast(&y[0]);
|
||||
s.z=thrust::raw_pointer_cast(&z[0]);
|
||||
s.ix=thrust::raw_pointer_cast(&ix[0]);
|
||||
s.iy=thrust::raw_pointer_cast(&iy[0]);
|
||||
s.iz=thrust::raw_pointer_cast(&iz[0]);
|
||||
s.aabbMin=thrust::raw_pointer_cast(&aabbMin[0]);
|
||||
s.aabbMax=thrust::raw_pointer_cast(&aabbMax[0]);
|
||||
|
||||
thrust::counting_iterator<int> it(0);
|
||||
thrust::for_each(it, it+unique_labels, s);
|
||||
}
|
||||
|
||||
//! Separates the left and right children of each node into continuous parts of the array.
|
||||
//! More specifically, it seperates children with even and odd node indices because nodes are always
|
||||
//! allocated in pairs -> child1==child2+1 -> child1 even and child2 odd, or vice-versa.
|
||||
//! Since the split operation is stable, this results in continuous partitions
|
||||
//! for all the single nodes.
|
||||
//! (basically the split primitive according to sengupta et al)
|
||||
//! about twice as fast as thrust::partition
|
||||
void separate_left_and_right_children( thrust::device_vector<int>& key_in, thrust::device_vector<int>& val_in, thrust::device_vector<int>& key_out, thrust::device_vector<int>& val_out, thrust::device_vector<int>& left_right_marks, bool scatter_val_out=true )
|
||||
{
|
||||
thrust::device_vector<int>* f_tmp = &val_out;
|
||||
thrust::device_vector<int>* addr_tmp = tmp_misc_;
|
||||
|
||||
thrust::exclusive_scan( /*thrust::make_transform_iterator(*/ left_right_marks.begin() /*,cuda::kd_tree_builder_detail::IsEven*/
|
||||
/*())*/, /*thrust::make_transform_iterator(*/ left_right_marks.end() /*,cuda::kd_tree_builder_detail::IsEven*/
|
||||
/*())*/, f_tmp->begin() );
|
||||
cuda::kd_tree_builder_detail::set_addr3 sa;
|
||||
sa.val_=thrust::raw_pointer_cast(&left_right_marks[0]);
|
||||
sa.f_=thrust::raw_pointer_cast(&(*f_tmp)[0]);
|
||||
sa.npoints_=key_in.size();
|
||||
thrust::counting_iterator<int> it(0);
|
||||
thrust::transform(it, it+val_in.size(), addr_tmp->begin(), sa);
|
||||
|
||||
thrust::scatter(key_in.begin(), key_in.end(), addr_tmp->begin(), key_out.begin());
|
||||
if( scatter_val_out ) thrust::scatter(val_in.begin(), val_in.end(), addr_tmp->begin(), val_out.begin());
|
||||
}
|
||||
|
||||
//! allocates additional space in all the node-related vectors.
|
||||
//! new_size elements will be added to all vectors.
|
||||
void resize_node_vectors( size_t new_size )
|
||||
{
|
||||
size_t add = new_size - child1_->size();
|
||||
child1_->insert(child1_->end(), add, -1);
|
||||
parent_->insert(parent_->end(), add, -1);
|
||||
cuda::kd_tree_builder_detail::SplitInfo s;
|
||||
s.left=0;
|
||||
s.right=0;
|
||||
splits_->insert(splits_->end(), add, s);
|
||||
float4 f;
|
||||
aabb_min_->insert(aabb_min_->end(), add, f);
|
||||
aabb_max_->insert(aabb_max_->end(), add, f);
|
||||
}
|
||||
|
||||
|
||||
const thrust::device_vector<float4>* points_;
|
||||
|
||||
// tree data, those are stored per-node
|
||||
|
||||
//! left child of each node. (right child==left child + 1, due to the alloc mechanism)
|
||||
//! child1_[node]==-1 if node is a leaf node
|
||||
thrust::device_vector<int>* child1_;
|
||||
//! parent node of each node
|
||||
thrust::device_vector<int>* parent_;
|
||||
//! split info (dim/value or left/right pointers)
|
||||
thrust::device_vector<cuda::kd_tree_builder_detail::SplitInfo>* splits_;
|
||||
//! min aabb value of each node
|
||||
thrust::device_vector<float4>* aabb_min_;
|
||||
//! max aabb value of each node
|
||||
thrust::device_vector<float4>* aabb_max_;
|
||||
|
||||
enum AllocationInfo
|
||||
{
|
||||
NodeCount=0,
|
||||
NodesAllocated=1,
|
||||
OutOfSpace=2
|
||||
};
|
||||
// those were put into a single vector of 3 elements so that only one mem transfer will be needed for all three of them
|
||||
// thrust::device_vector<int> out_of_space_;
|
||||
// thrust::device_vector<int> node_count_;
|
||||
// thrust::device_vector<int> nodes_allocated_;
|
||||
thrust::device_vector<int> allocation_info_;
|
||||
|
||||
int max_leaf_size_;
|
||||
|
||||
// coordinate values of the points
|
||||
thrust::device_vector<float>* points_x_, * points_y_, * points_z_;
|
||||
// indices
|
||||
thrust::device_vector<int>* index_x_, * index_y_, * index_z_;
|
||||
// owner node
|
||||
thrust::device_vector<int>* owners_x_, * owners_y_, * owners_z_;
|
||||
// contains info about whether a point was partitioned to the left or right child after a split
|
||||
thrust::device_vector<int>* leftright_x_, * leftright_y_, * leftright_z_;
|
||||
thrust::device_vector<int>* tmp_index_, * tmp_owners_, * tmp_misc_;
|
||||
bool delete_node_info_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace flann
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2011 Marius Muja ([email protected]). All rights reserved.
|
||||
* Copyright 2008-2011 David G. Lowe ([email protected]). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef FLANN_CONFIG_H_
|
||||
#define FLANN_CONFIG_H_
|
||||
|
||||
#ifdef FLANN_VERSION_
|
||||
#undef FLANN_VERSION_
|
||||
#endif
|
||||
#define FLANN_VERSION_ "${FLANN_VERSION}"
|
||||
|
||||
#endif /* FLANN_CONFIG_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,609 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja ([email protected]). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe ([email protected]). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_H_
|
||||
#define FLANN_H_
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
using namespace flann;
|
||||
#endif
|
||||
|
||||
|
||||
struct FLANNParameters
|
||||
{
|
||||
enum flann_algorithm_t algorithm; /* the algorithm to use */
|
||||
|
||||
/* search time parameters */
|
||||
int checks; /* how many leafs (features) to check in one search */
|
||||
float eps; /* eps parameter for eps-knn search */
|
||||
int sorted; /* indicates if results returned by radius search should be sorted or not */
|
||||
int max_neighbors; /* limits the maximum number of neighbors should be returned by radius search */
|
||||
int cores; /* number of paralel cores to use for searching */
|
||||
|
||||
/* kdtree index parameters */
|
||||
int trees; /* number of randomized trees to use (for kdtree) */
|
||||
int leaf_max_size;
|
||||
|
||||
/* kmeans index parameters */
|
||||
int branching; /* branching factor (for kmeans tree) */
|
||||
int iterations; /* max iterations to perform in one kmeans cluetering (kmeans tree) */
|
||||
enum flann_centers_init_t centers_init; /* algorithm used for picking the initial cluster centers for kmeans tree */
|
||||
float cb_index; /* cluster boundary index. Used when searching the kmeans tree */
|
||||
|
||||
/* autotuned index parameters */
|
||||
float target_precision; /* precision desired (used for autotuning, -1 otherwise) */
|
||||
float build_weight; /* build tree time weighting factor */
|
||||
float memory_weight; /* index memory weigthing factor */
|
||||
float sample_fraction; /* what fraction of the dataset to use for autotuning */
|
||||
|
||||
/* LSH parameters */
|
||||
unsigned int table_number_; /** The number of hash tables to use */
|
||||
unsigned int key_size_; /** The length of the key in the hash tables */
|
||||
unsigned int multi_probe_level_; /** Number of levels to use in multi-probe LSH, 0 for standard LSH */
|
||||
|
||||
/* other parameters */
|
||||
enum flann_log_level_t log_level; /* determines the verbosity of each flann function */
|
||||
long random_seed; /* random seed to use */
|
||||
};
|
||||
|
||||
|
||||
typedef void* FLANN_INDEX; /* deprecated */
|
||||
typedef void* flann_index_t;
|
||||
|
||||
FLANN_EXPORT extern struct FLANNParameters DEFAULT_FLANN_PARAMETERS;
|
||||
|
||||
/**
|
||||
Sets the log level used for all flann functions (unless
|
||||
specified in FLANNParameters for each call
|
||||
|
||||
Params:
|
||||
level = verbosity level
|
||||
*/
|
||||
FLANN_EXPORT void flann_log_verbosity(int level);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the distance type to use throughout FLANN.
|
||||
* If distance type specified is MINKOWSKI, the second argument
|
||||
* specifies which order the minkowski distance should have.
|
||||
*/
|
||||
FLANN_EXPORT void flann_set_distance_type(enum flann_distance_t distance_type, int order);
|
||||
|
||||
/**
|
||||
* Gets the distance type in use throughout FLANN.
|
||||
*/
|
||||
FLANN_EXPORT enum flann_distance_t flann_get_distance_type();
|
||||
|
||||
/**
|
||||
* Gets the distance order in use throughout FLANN (only applicable if minkowski distance
|
||||
* is in use).
|
||||
*/
|
||||
FLANN_EXPORT int flann_get_distance_order();
|
||||
|
||||
/**
|
||||
Builds and returns an index. It uses autotuning if the target_precision field of index_params
|
||||
is between 0 and 1, or the parameters specified if it's -1.
|
||||
|
||||
Params:
|
||||
dataset = pointer to a data set stored in row major order
|
||||
rows = number of rows (features) in the dataset
|
||||
cols = number of columns in the dataset (feature dimensionality)
|
||||
speedup = speedup over linear search, estimated if using autotuning, output parameter
|
||||
index_params = index related parameters
|
||||
flann_params = generic flann parameters
|
||||
|
||||
Returns: the newly created index or a number <0 for error
|
||||
*/
|
||||
FLANN_EXPORT flann_index_t flann_build_index(float* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
float* speedup,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT flann_index_t flann_build_index_float(float* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
float* speedup,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT flann_index_t flann_build_index_double(double* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
float* speedup,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT flann_index_t flann_build_index_byte(unsigned char* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
float* speedup,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT flann_index_t flann_build_index_int(int* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
float* speedup,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
/**
|
||||
Adds points to pre-built index.
|
||||
|
||||
Params:
|
||||
index_ptr = pointer to index, must already be built
|
||||
points = pointer to array of points
|
||||
rows = number of points to add
|
||||
columns = feature dimensionality
|
||||
rebuild_threshold = reallocs index when it grows by factor of
|
||||
`rebuild_threshold`. A smaller value results is more space efficient
|
||||
but less computationally efficient. Must be greater than 1.
|
||||
|
||||
Returns: 0 if success otherwise -1
|
||||
**/
|
||||
FLANN_EXPORT int flann_add_points(flann_index_t index_ptr, float* points,
|
||||
int rows, int columns,
|
||||
float rebuild_threshold);
|
||||
|
||||
FLANN_EXPORT int flann_add_points_float(flann_index_t index_ptr, float* points,
|
||||
int rows, int columns,
|
||||
float rebuild_threshold);
|
||||
|
||||
FLANN_EXPORT int flann_add_points_double(flann_index_t index_ptr,
|
||||
double* points, int rows, int columns,
|
||||
float rebuild_threshold);
|
||||
|
||||
FLANN_EXPORT int flann_add_points_byte(flann_index_t index_ptr,
|
||||
unsigned char* points, int rows,
|
||||
int columns, float rebuild_threshold);
|
||||
|
||||
FLANN_EXPORT int flann_add_points_int(flann_index_t index_ptr, int* points,
|
||||
int rows, int columns,
|
||||
float rebuild_threshold);
|
||||
|
||||
/**
|
||||
* Removes a point from a pre-built index.
|
||||
*
|
||||
* index_ptr = pointer to pre-built index.
|
||||
* point_id = index of datapoint to remove.
|
||||
*/
|
||||
FLANN_EXPORT int flann_remove_point(flann_index_t index_ptr,
|
||||
unsigned int point_id);
|
||||
|
||||
FLANN_EXPORT int flann_remove_point_float(flann_index_t index_ptr,
|
||||
unsigned int point_id);
|
||||
|
||||
FLANN_EXPORT int flann_remove_point_double(flann_index_t index_ptr,
|
||||
unsigned int point_id);
|
||||
|
||||
FLANN_EXPORT int flann_remove_point_byte(flann_index_t index_ptr,
|
||||
unsigned int point_id);
|
||||
|
||||
FLANN_EXPORT int flann_remove_point_int(flann_index_t index_ptr,
|
||||
unsigned int point_id);
|
||||
|
||||
/**
|
||||
* Gets a point from a given index position.
|
||||
*
|
||||
* index_ptr = pointer to pre-built index.
|
||||
* point_id = index of datapoint to get.
|
||||
*
|
||||
* Returns: pointer to datapoint or NULL on miss
|
||||
*/
|
||||
FLANN_EXPORT float* flann_get_point(flann_index_t index_ptr,
|
||||
unsigned int point_id);
|
||||
|
||||
FLANN_EXPORT float* flann_get_point_float(flann_index_t index_ptr,
|
||||
unsigned int point_id);
|
||||
|
||||
FLANN_EXPORT double* flann_get_point_double(flann_index_t index_ptr,
|
||||
unsigned int point_id);
|
||||
|
||||
FLANN_EXPORT unsigned char* flann_get_point_byte(flann_index_t index_ptr,
|
||||
unsigned int point_id);
|
||||
|
||||
FLANN_EXPORT int* flann_get_point_int(flann_index_t index_ptr,
|
||||
unsigned int point_id);
|
||||
|
||||
/**
|
||||
* Returns the number of datapoints stored in index.
|
||||
*
|
||||
* index_ptr = pointer to pre-built index.
|
||||
*
|
||||
*/
|
||||
FLANN_EXPORT unsigned int flann_veclen(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT unsigned int flann_veclen_float(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT unsigned int flann_veclen_double(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT unsigned int flann_veclen_byte(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT unsigned int flann_veclen_int(flann_index_t index_ptr);
|
||||
|
||||
/**
|
||||
* Returns the dimensionality of datapoints stored in index.
|
||||
*
|
||||
* index_ptr = pointer to pre-built index.
|
||||
*
|
||||
*/
|
||||
FLANN_EXPORT unsigned int flann_size(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT unsigned int flann_size_float(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT unsigned int flann_size_double(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT unsigned int flann_size_byte(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT unsigned int flann_size_int(flann_index_t index_ptr);
|
||||
|
||||
/**
|
||||
* Returns the number of bytes consumed by the index.
|
||||
*
|
||||
* index_ptr = pointer to pre-built index.
|
||||
*
|
||||
*/
|
||||
FLANN_EXPORT int flann_used_memory(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT int flann_used_memory_float(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT int flann_used_memory_double(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT int flann_used_memory_byte(flann_index_t index_ptr);
|
||||
|
||||
FLANN_EXPORT int flann_used_memory_int(flann_index_t index_ptr);
|
||||
|
||||
|
||||
/**
|
||||
* Saves the index to a file. Only the index is saved into the file, the dataset corresponding to the index is not saved.
|
||||
*
|
||||
* @param index_id The index that should be saved
|
||||
* @param filename The filename the index should be saved to
|
||||
* @return Returns 0 on success, negative value on error.
|
||||
*/
|
||||
FLANN_EXPORT int flann_save_index(flann_index_t index_id,
|
||||
char* filename);
|
||||
|
||||
FLANN_EXPORT int flann_save_index_float(flann_index_t index_id,
|
||||
char* filename);
|
||||
|
||||
FLANN_EXPORT int flann_save_index_double(flann_index_t index_id,
|
||||
char* filename);
|
||||
|
||||
FLANN_EXPORT int flann_save_index_byte(flann_index_t index_id,
|
||||
char* filename);
|
||||
|
||||
FLANN_EXPORT int flann_save_index_int(flann_index_t index_id,
|
||||
char* filename);
|
||||
|
||||
/**
|
||||
* Loads an index from a file.
|
||||
*
|
||||
* @param filename File to load the index from.
|
||||
* @param dataset The dataset corresponding to the index.
|
||||
* @param rows Dataset tors
|
||||
* @param cols Dataset columns
|
||||
* @return
|
||||
*/
|
||||
FLANN_EXPORT flann_index_t flann_load_index(char* filename,
|
||||
float* dataset,
|
||||
int rows,
|
||||
int cols);
|
||||
|
||||
FLANN_EXPORT flann_index_t flann_load_index_float(char* filename,
|
||||
float* dataset,
|
||||
int rows,
|
||||
int cols);
|
||||
|
||||
FLANN_EXPORT flann_index_t flann_load_index_double(char* filename,
|
||||
double* dataset,
|
||||
int rows,
|
||||
int cols);
|
||||
|
||||
FLANN_EXPORT flann_index_t flann_load_index_byte(char* filename,
|
||||
unsigned char* dataset,
|
||||
int rows,
|
||||
int cols);
|
||||
|
||||
FLANN_EXPORT flann_index_t flann_load_index_int(char* filename,
|
||||
int* dataset,
|
||||
int rows,
|
||||
int cols);
|
||||
|
||||
|
||||
/**
|
||||
Builds an index and uses it to find nearest neighbors.
|
||||
|
||||
Params:
|
||||
dataset = pointer to a data set stored in row major order
|
||||
rows = number of rows (features) in the dataset
|
||||
cols = number of columns in the dataset (feature dimensionality)
|
||||
testset = pointer to a query set stored in row major order
|
||||
trows = number of rows (features) in the query dataset (same dimensionality as features in the dataset)
|
||||
indices = pointer to matrix for the indices of the nearest neighbors of the testset features in the dataset
|
||||
(must have trows number of rows and nn number of columns)
|
||||
nn = how many nearest neighbors to return
|
||||
flann_params = generic flann parameters
|
||||
|
||||
Returns: zero or -1 for error
|
||||
*/
|
||||
FLANN_EXPORT int flann_find_nearest_neighbors(float* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
float* testset,
|
||||
int trows,
|
||||
int* indices,
|
||||
float* dists,
|
||||
int nn,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_find_nearest_neighbors_float(float* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
float* testset,
|
||||
int trows,
|
||||
int* indices,
|
||||
float* dists,
|
||||
int nn,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_find_nearest_neighbors_double(double* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
double* testset,
|
||||
int trows,
|
||||
int* indices,
|
||||
double* dists,
|
||||
int nn,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_find_nearest_neighbors_byte(unsigned char* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
unsigned char* testset,
|
||||
int trows,
|
||||
int* indices,
|
||||
float* dists,
|
||||
int nn,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_find_nearest_neighbors_int(int* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
int* testset,
|
||||
int trows,
|
||||
int* indices,
|
||||
float* dists,
|
||||
int nn,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
|
||||
/**
|
||||
Searches for nearest neighbors using the index provided
|
||||
|
||||
Params:
|
||||
index_id = the index (constructed previously using flann_build_index).
|
||||
testset = pointer to a query set stored in row major order
|
||||
trows = number of rows (features) in the query dataset (same dimensionality as features in the dataset)
|
||||
indices = pointer to matrix for the indices of the nearest neighbors of the testset features in the dataset
|
||||
(must have trows number of rows and nn number of columns)
|
||||
dists = pointer to matrix for the distances of the nearest neighbors of the testset features in the dataset
|
||||
(must have trows number of rows and 1 column)
|
||||
nn = how many nearest neighbors to return
|
||||
flann_params = generic flann parameters
|
||||
|
||||
Returns: zero or a number <0 for error
|
||||
*/
|
||||
FLANN_EXPORT int flann_find_nearest_neighbors_index(flann_index_t index_id,
|
||||
float* testset,
|
||||
int trows,
|
||||
int* indices,
|
||||
float* dists,
|
||||
int nn,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_find_nearest_neighbors_index_float(flann_index_t index_id,
|
||||
float* testset,
|
||||
int trows,
|
||||
int* indices,
|
||||
float* dists,
|
||||
int nn,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_find_nearest_neighbors_index_double(flann_index_t index_id,
|
||||
double* testset,
|
||||
int trows,
|
||||
int* indices,
|
||||
double* dists,
|
||||
int nn,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_find_nearest_neighbors_index_byte(flann_index_t index_id,
|
||||
unsigned char* testset,
|
||||
int trows,
|
||||
int* indices,
|
||||
float* dists,
|
||||
int nn,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_find_nearest_neighbors_index_int(flann_index_t index_id,
|
||||
int* testset,
|
||||
int trows,
|
||||
int* indices,
|
||||
float* dists,
|
||||
int nn,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
|
||||
/**
|
||||
* Performs an radius search using an already constructed index.
|
||||
*
|
||||
* In case of radius search, instead of always returning a predetermined
|
||||
* number of nearest neighbours (for example the 10 nearest neighbours), the
|
||||
* search will return all the neighbours found within a search radius
|
||||
* of the query point.
|
||||
*
|
||||
* The check parameter in the FLANNParameters below sets the level of approximation
|
||||
* for the search by only visiting "checks" number of features in the index
|
||||
* (the same way as for the KNN search). A lower value for checks will give
|
||||
* a higher search speedup at the cost of potentially not returning all the
|
||||
* neighbours in the specified radius.
|
||||
*/
|
||||
FLANN_EXPORT int flann_radius_search(flann_index_t index_ptr, /* the index */
|
||||
float* query, /* query point */
|
||||
int* indices, /* array for storing the indices found (will be modified) */
|
||||
float* dists, /* similar, but for storing distances */
|
||||
int max_nn, /* size of arrays indices and dists */
|
||||
float radius, /* search radius (squared radius for euclidian metric) */
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_radius_search_float(flann_index_t index_ptr, /* the index */
|
||||
float* query, /* query point */
|
||||
int* indices, /* array for storing the indices found (will be modified) */
|
||||
float* dists, /* similar, but for storing distances */
|
||||
int max_nn, /* size of arrays indices and dists */
|
||||
float radius, /* search radius (squared radius for euclidian metric) */
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_radius_search_double(flann_index_t index_ptr, /* the index */
|
||||
double* query, /* query point */
|
||||
int* indices, /* array for storing the indices found (will be modified) */
|
||||
double* dists, /* similar, but for storing distances */
|
||||
int max_nn, /* size of arrays indices and dists */
|
||||
float radius, /* search radius (squared radius for euclidian metric) */
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_radius_search_byte(flann_index_t index_ptr, /* the index */
|
||||
unsigned char* query, /* query point */
|
||||
int* indices, /* array for storing the indices found (will be modified) */
|
||||
float* dists, /* similar, but for storing distances */
|
||||
int max_nn, /* size of arrays indices and dists */
|
||||
float radius, /* search radius (squared radius for euclidian metric) */
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_radius_search_int(flann_index_t index_ptr, /* the index */
|
||||
int* query, /* query point */
|
||||
int* indices, /* array for storing the indices found (will be modified) */
|
||||
float* dists, /* similar, but for storing distances */
|
||||
int max_nn, /* size of arrays indices and dists */
|
||||
float radius, /* search radius (squared radius for euclidian metric) */
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
/**
|
||||
Deletes an index and releases the memory used by it.
|
||||
|
||||
Params:
|
||||
index_id = the index (constructed previously using flann_build_index).
|
||||
flann_params = generic flann parameters
|
||||
|
||||
Returns: zero or a number <0 for error
|
||||
*/
|
||||
FLANN_EXPORT int flann_free_index(flann_index_t index_id,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_free_index_float(flann_index_t index_id,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_free_index_double(flann_index_t index_id,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_free_index_byte(flann_index_t index_id,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_free_index_int(flann_index_t index_id,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
/**
|
||||
Clusters the features in the dataset using a hierarchical kmeans clustering approach.
|
||||
This is significantly faster than using a flat kmeans clustering for a large number
|
||||
of clusters.
|
||||
|
||||
Params:
|
||||
dataset = pointer to a data set stored in row major order
|
||||
rows = number of rows (features) in the dataset
|
||||
cols = number of columns in the dataset (feature dimensionality)
|
||||
clusters = number of cluster to compute
|
||||
result = memory buffer where the output cluster centers are storred
|
||||
index_params = used to specify the kmeans tree parameters (branching factor, max number of iterations to use)
|
||||
flann_params = generic flann parameters
|
||||
|
||||
Returns: number of clusters computed or a number <0 for error. This number can be different than the number of clusters requested, due to the
|
||||
way hierarchical clusters are computed. The number of clusters returned will be the highest number of the form
|
||||
(branch_size-1)*K+1 smaller than the number of clusters requested.
|
||||
*/
|
||||
|
||||
FLANN_EXPORT int flann_compute_cluster_centers(float* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
int clusters,
|
||||
float* result,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_compute_cluster_centers_float(float* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
int clusters,
|
||||
float* result,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_compute_cluster_centers_double(double* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
int clusters,
|
||||
double* result,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_compute_cluster_centers_byte(unsigned char* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
int clusters,
|
||||
float* result,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
FLANN_EXPORT int flann_compute_cluster_centers_int(int* dataset,
|
||||
int rows,
|
||||
int cols,
|
||||
int clusters,
|
||||
float* result,
|
||||
struct FLANNParameters* flann_params);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
|
||||
#include "flann.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /*FLANN_H_*/
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja ([email protected]). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe ([email protected]). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#include "flann/flann.hpp"
|
||||
@@ -1,231 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja ([email protected]). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe ([email protected]). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef FLANN_HDF5_H_
|
||||
#define FLANN_HDF5_H_
|
||||
|
||||
#include <hdf5.h>
|
||||
|
||||
#include "flann/util/matrix.h"
|
||||
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
hid_t get_hdf5_type()
|
||||
{
|
||||
throw FLANNException("Unsupported type for IO operations");
|
||||
}
|
||||
|
||||
template<>
|
||||
hid_t get_hdf5_type<char>() { return H5T_NATIVE_CHAR; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<unsigned char>() { return H5T_NATIVE_UCHAR; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<short int>() { return H5T_NATIVE_SHORT; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<unsigned short int>() { return H5T_NATIVE_USHORT; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<int>() { return H5T_NATIVE_INT; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<unsigned int>() { return H5T_NATIVE_UINT; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<long>() { return H5T_NATIVE_LONG; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<unsigned long>() { return H5T_NATIVE_ULONG; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<float>() { return H5T_NATIVE_FLOAT; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<double>() { return H5T_NATIVE_DOUBLE; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<long double>() { return H5T_NATIVE_LDOUBLE; }
|
||||
}
|
||||
|
||||
|
||||
#define CHECK_ERROR(x,y) if ((x)<0) throw FLANNException((y));
|
||||
|
||||
template<typename T>
|
||||
void save_to_file(const flann::Matrix<T>& dataset, const std::string& filename, const std::string& name)
|
||||
{
|
||||
|
||||
#if H5Eset_auto_vers == 2
|
||||
H5Eset_auto( H5E_DEFAULT, NULL, NULL );
|
||||
#else
|
||||
H5Eset_auto( NULL, NULL );
|
||||
#endif
|
||||
|
||||
herr_t status;
|
||||
hid_t file_id;
|
||||
file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
|
||||
if (file_id < 0) {
|
||||
file_id = H5Fcreate(filename.c_str(), H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT);
|
||||
}
|
||||
CHECK_ERROR(file_id,"Error creating hdf5 file.");
|
||||
|
||||
hsize_t dimsf[2]; // dataset dimensions
|
||||
dimsf[0] = dataset.rows;
|
||||
dimsf[1] = dataset.cols;
|
||||
|
||||
hid_t space_id = H5Screate_simple(2, dimsf, NULL);
|
||||
hid_t memspace_id = H5Screate_simple(2, dimsf, NULL);
|
||||
|
||||
hid_t dataset_id;
|
||||
#if H5Dcreate_vers == 2
|
||||
dataset_id = H5Dcreate2(file_id, name.c_str(), get_hdf5_type<T>(), space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
||||
#else
|
||||
dataset_id = H5Dcreate(file_id, name.c_str(), get_hdf5_type<T>(), space_id, H5P_DEFAULT);
|
||||
#endif
|
||||
|
||||
if (dataset_id<0) {
|
||||
#if H5Dopen_vers == 2
|
||||
dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT);
|
||||
#else
|
||||
dataset_id = H5Dopen(file_id, name.c_str());
|
||||
#endif
|
||||
}
|
||||
CHECK_ERROR(dataset_id,"Error creating or opening dataset in file.");
|
||||
|
||||
status = H5Dwrite(dataset_id, get_hdf5_type<T>(), memspace_id, space_id, H5P_DEFAULT, dataset.ptr() );
|
||||
CHECK_ERROR(status, "Error writing to dataset");
|
||||
|
||||
H5Sclose(memspace_id);
|
||||
H5Sclose(space_id);
|
||||
H5Dclose(dataset_id);
|
||||
H5Fclose(file_id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void load_from_file(flann::Matrix<T>& dataset, const std::string& filename, const std::string& name)
|
||||
{
|
||||
herr_t status;
|
||||
hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
|
||||
CHECK_ERROR(file_id,"Error opening hdf5 file.");
|
||||
|
||||
hid_t dataset_id;
|
||||
#if H5Dopen_vers == 2
|
||||
dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT);
|
||||
#else
|
||||
dataset_id = H5Dopen(file_id, name.c_str());
|
||||
#endif
|
||||
CHECK_ERROR(dataset_id,"Error opening dataset in file.");
|
||||
|
||||
hid_t space_id = H5Dget_space(dataset_id);
|
||||
|
||||
hsize_t dims_out[2];
|
||||
H5Sget_simple_extent_dims(space_id, dims_out, NULL);
|
||||
|
||||
dataset = flann::Matrix<T>(new T[dims_out[0]*dims_out[1]], dims_out[0], dims_out[1]);
|
||||
|
||||
status = H5Dread(dataset_id, get_hdf5_type<T>(), H5S_ALL, H5S_ALL, H5P_DEFAULT, dataset[0]);
|
||||
CHECK_ERROR(status, "Error reading dataset");
|
||||
|
||||
H5Sclose(space_id);
|
||||
H5Dclose(dataset_id);
|
||||
H5Fclose(file_id);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_MPI
|
||||
|
||||
namespace mpi
|
||||
{
|
||||
/**
|
||||
* Loads a the hyperslice corresponding to this processor from a hdf5 file.
|
||||
* @param flann_dataset Dataset where the data is loaded
|
||||
* @param filename HDF5 file name
|
||||
* @param name Name of dataset inside file
|
||||
*/
|
||||
template<typename T>
|
||||
void load_from_file(flann::Matrix<T>& dataset, const std::string& filename, const std::string& name)
|
||||
{
|
||||
MPI_Comm comm = MPI_COMM_WORLD;
|
||||
MPI_Info info = MPI_INFO_NULL;
|
||||
|
||||
int mpi_size, mpi_rank;
|
||||
MPI_Comm_size(comm, &mpi_size);
|
||||
MPI_Comm_rank(comm, &mpi_rank);
|
||||
|
||||
herr_t status;
|
||||
|
||||
hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS);
|
||||
H5Pset_fapl_mpio(plist_id, comm, info);
|
||||
hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, plist_id);
|
||||
CHECK_ERROR(file_id,"Error opening hdf5 file.");
|
||||
H5Pclose(plist_id);
|
||||
hid_t dataset_id;
|
||||
#if H5Dopen_vers == 2
|
||||
dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT);
|
||||
#else
|
||||
dataset_id = H5Dopen(file_id, name.c_str());
|
||||
#endif
|
||||
CHECK_ERROR(dataset_id,"Error opening dataset in file.");
|
||||
|
||||
hid_t space_id = H5Dget_space(dataset_id);
|
||||
hsize_t dims[2];
|
||||
H5Sget_simple_extent_dims(space_id, dims, NULL);
|
||||
|
||||
hsize_t count[2];
|
||||
hsize_t offset[2];
|
||||
|
||||
hsize_t item_cnt = dims[0]/mpi_size+(dims[0]%mpi_size==0 ? 0 : 1);
|
||||
hsize_t cnt = (mpi_rank<mpi_size-1 ? item_cnt : dims[0]-item_cnt*(mpi_size-1));
|
||||
|
||||
count[0] = cnt;
|
||||
count[1] = dims[1];
|
||||
offset[0] = mpi_rank*item_cnt;
|
||||
offset[1] = 0;
|
||||
|
||||
hid_t memspace_id = H5Screate_simple(2,count,NULL);
|
||||
|
||||
H5Sselect_hyperslab(space_id, H5S_SELECT_SET, offset, NULL, count, NULL);
|
||||
|
||||
dataset = flann::Matrix<T>(new T[count[0]*count[1]], count[0], count[1]);
|
||||
|
||||
plist_id = H5Pcreate(H5P_DATASET_XFER);
|
||||
// H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);
|
||||
status = H5Dread(dataset_id, get_hdf5_type<T>(), memspace_id, space_id, plist_id, dataset[0]);
|
||||
CHECK_ERROR(status, "Error reading dataset");
|
||||
|
||||
H5Pclose(plist_id);
|
||||
H5Sclose(space_id);
|
||||
H5Sclose(memspace_id);
|
||||
H5Dclose(dataset_id);
|
||||
H5Fclose(file_id);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_MPI
|
||||
} // namespace flann::mpi
|
||||
|
||||
#endif /* FLANN_HDF5_H_ */
|
||||
@@ -1,89 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2011 Marius Muja ([email protected]). All rights reserved.
|
||||
* Copyright 2008-2011 David G. Lowe ([email protected]). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef MPI_CLIENT_H_
|
||||
#define MPI_CLIENT_H_
|
||||
|
||||
#include <cstdlib>
|
||||
#include <boost/asio.hpp>
|
||||
#include <flann/util/matrix.h>
|
||||
#include <flann/util/params.h>
|
||||
#include "queries.h"
|
||||
|
||||
namespace flann {
|
||||
namespace mpi {
|
||||
|
||||
|
||||
class Client
|
||||
{
|
||||
public:
|
||||
Client(const std::string& host, const std::string& service)
|
||||
{
|
||||
tcp::resolver resolver(io_service_);
|
||||
tcp::resolver::query query(tcp::v4(), host, service);
|
||||
iterator_ = resolver.resolve(query);
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementType, typename DistanceType>
|
||||
void knnSearch(const flann::Matrix<ElementType>& queries, flann::Matrix<int>& indices, flann::Matrix<DistanceType>& dists, int knn, const SearchParams& params)
|
||||
{
|
||||
tcp::socket sock(io_service_);
|
||||
sock.connect(*iterator_);
|
||||
|
||||
Request<ElementType> req;
|
||||
req.nn = knn;
|
||||
req.queries = queries;
|
||||
req.checks = params.checks;
|
||||
// send request
|
||||
write_object(sock,req);
|
||||
|
||||
Response<DistanceType> resp;
|
||||
// read response
|
||||
read_object(sock, resp);
|
||||
|
||||
for (size_t i=0;i<indices.rows;++i) {
|
||||
for (size_t j=0;j<indices.cols;++j) {
|
||||
indices[i][j] = resp.indices[i][j];
|
||||
dists[i][j] = resp.dists[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
boost::asio::io_service io_service_;
|
||||
tcp::resolver::iterator iterator_;
|
||||
};
|
||||
|
||||
|
||||
} //namespace mpi
|
||||
} // namespace flann
|
||||
|
||||
#endif // MPI_CLIENT_H_
|
||||
@@ -1,85 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <flann/util/params.h>
|
||||
#include <flann/io/hdf5.h>
|
||||
#include <flann/mpi/client.h>
|
||||
|
||||
|
||||
|
||||
#define IF_RANK0 if (world.rank()==0)
|
||||
|
||||
timeval start_time_;
|
||||
void start_timer(const std::string& message = "")
|
||||
{
|
||||
if (!message.empty()) {
|
||||
printf("%s", message.c_str());
|
||||
fflush(stdout);
|
||||
}
|
||||
gettimeofday(&start_time_,NULL);
|
||||
}
|
||||
|
||||
double stop_timer()
|
||||
{
|
||||
timeval end_time;
|
||||
gettimeofday(&end_time,NULL);
|
||||
|
||||
return double(end_time.tv_sec-start_time_.tv_sec)+ double(end_time.tv_usec-start_time_.tv_usec)/1000000;
|
||||
}
|
||||
|
||||
float compute_precision(const flann::Matrix<int>& match, const flann::Matrix<int>& indices)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
assert(match.rows == indices.rows);
|
||||
size_t nn = std::min(match.cols, indices.cols);
|
||||
|
||||
for(size_t i=0; i<match.rows; ++i) {
|
||||
for (size_t j=0;j<nn;++j) {
|
||||
for (size_t k=0;k<nn;++k) {
|
||||
if (match[i][j]==indices[i][k]) {
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return float(count)/(nn*match.rows);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try {
|
||||
|
||||
flann::Matrix<float> query;
|
||||
flann::Matrix<int> match;
|
||||
|
||||
flann::load_from_file(query, "sift100K.h5","query");
|
||||
flann::load_from_file(match, "sift100K.h5","match");
|
||||
// flann::load_from_file(gt_dists, "sift100K.h5","dists");
|
||||
|
||||
flann::mpi::Client index("localhost","9999");
|
||||
|
||||
int nn = 1;
|
||||
flann::Matrix<int> indices(new int[query.rows*nn], query.rows, nn);
|
||||
flann::Matrix<float> dists(new float[query.rows*nn], query.rows, nn);
|
||||
|
||||
start_timer("Performing search...\n");
|
||||
index.knnSearch(query, indices, dists, nn, flann::SearchParams(64));
|
||||
printf("Search done (%g seconds)\n", stop_timer());
|
||||
|
||||
printf("Checking results\n");
|
||||
float precision = compute_precision(match, indices);
|
||||
printf("Precision is: %g\n", precision);
|
||||
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
std::cerr << "Exception: " << e.what() << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#include <boost/mpi.hpp>
|
||||
#include <flann/mpi/server.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::mpi::environment env(argc, argv);
|
||||
|
||||
try {
|
||||
if (argc != 4) {
|
||||
std::cout << "Usage: " << argv[0] << " <file> <dataset> <port>\n";
|
||||
return 1;
|
||||
}
|
||||
flann::mpi::Server<flann::L2<float> > server(argv[1], argv[2], std::atoi(argv[3]),
|
||||
flann::KDTreeIndexParams(4));
|
||||
|
||||
server.run();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
std::cerr << "Exception: " << e.what() << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2010 Marius Muja ([email protected]). All rights reserved.
|
||||
* Copyright 2008-2010 David G. Lowe ([email protected]). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef FLANN_MPI_HPP_
|
||||
#define FLANN_MPI_HPP_
|
||||
|
||||
#include <boost/mpi.hpp>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <flann/flann.hpp>
|
||||
#include <flann/io/hdf5.h>
|
||||
|
||||
namespace flann
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
template<typename DistanceType>
|
||||
struct SearchResults
|
||||
{
|
||||
flann::Matrix<int> indices;
|
||||
flann::Matrix<DistanceType> dists;
|
||||
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const unsigned int version)
|
||||
{
|
||||
ar& indices.rows;
|
||||
ar& indices.cols;
|
||||
if (Archive::is_loading::value) {
|
||||
indices = Matrix<int>(new int[indices.rows*indices.cols], indices.rows, indices.cols);
|
||||
}
|
||||
ar& boost::serialization::make_array(indices.ptr(), indices.rows*indices.cols);
|
||||
if (Archive::is_saving::value) {
|
||||
delete[] indices.ptr();
|
||||
}
|
||||
ar& dists.rows;
|
||||
ar& dists.cols;
|
||||
if (Archive::is_loading::value) {
|
||||
dists = Matrix<DistanceType>(new DistanceType[dists.rows*dists.cols], dists.rows, dists.cols);
|
||||
}
|
||||
ar& boost::serialization::make_array(dists.ptr(), dists.rows*dists.cols);
|
||||
if (Archive::is_saving::value) {
|
||||
delete[] dists.ptr();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename DistanceType>
|
||||
struct ResultsMerger
|
||||
{
|
||||
SearchResults<DistanceType> operator()(SearchResults<DistanceType> a, SearchResults<DistanceType> b)
|
||||
{
|
||||
SearchResults<DistanceType> results;
|
||||
results.indices = flann::Matrix<int>(new int[a.indices.rows*a.indices.cols],a.indices.rows,a.indices.cols);
|
||||
results.dists = flann::Matrix<DistanceType>(new DistanceType[a.dists.rows*a.dists.cols],a.dists.rows,a.dists.cols);
|
||||
|
||||
|
||||
for (size_t i = 0; i < results.dists.rows; ++i) {
|
||||
size_t idx = 0;
|
||||
size_t a_idx = 0;
|
||||
size_t b_idx = 0;
|
||||
while (idx < results.dists.cols) {
|
||||
if (a.dists[i][a_idx] <= b.dists[i][b_idx]) {
|
||||
results.dists[i][idx] = a.dists[i][a_idx];
|
||||
results.indices[i][idx] = a.indices[i][a_idx];
|
||||
idx++;
|
||||
a_idx++;
|
||||
}
|
||||
else {
|
||||
results.dists[i][idx] = b.dists[i][b_idx];
|
||||
results.indices[i][idx] = b.indices[i][b_idx];
|
||||
idx++;
|
||||
b_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] a.indices.ptr();
|
||||
delete[] a.dists.ptr();
|
||||
delete[] b.indices.ptr();
|
||||
delete[] b.dists.ptr();
|
||||
return results;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Distance>
|
||||
class Index
|
||||
{
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
flann::Index<Distance>* flann_index;
|
||||
flann::Matrix<ElementType> dataset;
|
||||
int size_;
|
||||
int offset_;
|
||||
|
||||
public:
|
||||
Index(const std::string& file_name,
|
||||
const std::string& dataset_name,
|
||||
const IndexParams& params);
|
||||
|
||||
~Index();
|
||||
|
||||
void buildIndex()
|
||||
{
|
||||
flann_index->buildIndex();
|
||||
}
|
||||
|
||||
void knnSearch(const flann::Matrix<ElementType>& queries,
|
||||
flann::Matrix<int>& indices,
|
||||
flann::Matrix<DistanceType>& dists,
|
||||
int knn, const
|
||||
SearchParams& params);
|
||||
|
||||
int radiusSearch(const flann::Matrix<ElementType>& query,
|
||||
flann::Matrix<int>& indices,
|
||||
flann::Matrix<DistanceType>& dists,
|
||||
float radius,
|
||||
const SearchParams& params);
|
||||
|
||||
// void save(std::string filename);
|
||||
|
||||
int veclen() const
|
||||
{
|
||||
return flann_index->veclen();
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
IndexParams getIndexParameters()
|
||||
{
|
||||
return flann_index->getParameters();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Distance>
|
||||
Index<Distance>::Index(const std::string& file_name, const std::string& dataset_name, const IndexParams& params)
|
||||
{
|
||||
boost::mpi::communicator world;
|
||||
flann_algorithm_t index_type = get_param<flann_algorithm_t>(params,"algorithm");
|
||||
if (index_type == FLANN_INDEX_SAVED) {
|
||||
throw FLANNException("Saving/loading of MPI indexes is not currently supported.");
|
||||
}
|
||||
flann::mpi::load_from_file(dataset, file_name, dataset_name);
|
||||
flann_index = new flann::Index<Distance>(dataset, params);
|
||||
|
||||
std::vector<int> sizes;
|
||||
// get the sizes of all MPI indices
|
||||
all_gather(world, (int)flann_index->size(), sizes);
|
||||
size_ = 0;
|
||||
offset_ = 0;
|
||||
for (size_t i = 0; i < sizes.size(); ++i) {
|
||||
if ((int)i < world.rank()) offset_ += sizes[i];
|
||||
size_ += sizes[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Distance>
|
||||
Index<Distance>::~Index()
|
||||
{
|
||||
delete flann_index;
|
||||
delete[] dataset.ptr();
|
||||
}
|
||||
|
||||
template<typename Distance>
|
||||
void Index<Distance>::knnSearch(const flann::Matrix<ElementType>& queries, flann::Matrix<int>& indices, flann::Matrix<DistanceType>& dists, int knn, const SearchParams& params)
|
||||
{
|
||||
boost::mpi::communicator world;
|
||||
flann::Matrix<int> local_indices(new int[queries.rows*knn], queries.rows, knn);
|
||||
flann::Matrix<DistanceType> local_dists(new DistanceType[queries.rows*knn], queries.rows, knn);
|
||||
|
||||
flann_index->knnSearch(queries, local_indices, local_dists, knn, params);
|
||||
for (size_t i = 0; i < local_indices.rows; ++i) {
|
||||
for (size_t j = 0; j < local_indices.cols; ++j) {
|
||||
local_indices[i][j] += offset_;
|
||||
}
|
||||
}
|
||||
SearchResults<DistanceType> local_results;
|
||||
local_results.indices = local_indices;
|
||||
local_results.dists = local_dists;
|
||||
SearchResults<DistanceType> results;
|
||||
|
||||
// perform MPI reduce
|
||||
reduce(world, local_results, results, ResultsMerger<DistanceType>(), 0);
|
||||
|
||||
if (world.rank() == 0) {
|
||||
for (size_t i = 0; i < results.indices.rows; ++i) {
|
||||
for (size_t j = 0; j < results.indices.cols; ++j) {
|
||||
indices[i][j] = results.indices[i][j];
|
||||
dists[i][j] = results.dists[i][j];
|
||||
}
|
||||
}
|
||||
delete[] results.indices.ptr();
|
||||
delete[] results.dists.ptr();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Distance>
|
||||
int Index<Distance>::radiusSearch(const flann::Matrix<ElementType>& query, flann::Matrix<int>& indices, flann::Matrix<DistanceType>& dists, float radius, const SearchParams& params)
|
||||
{
|
||||
boost::mpi::communicator world;
|
||||
flann::Matrix<int> local_indices(new int[indices.rows*indices.cols], indices.rows, indices.cols);
|
||||
flann::Matrix<DistanceType> local_dists(new DistanceType[dists.rows*dists.cols], dists.rows, dists.cols);
|
||||
|
||||
flann_index->radiusSearch(query, local_indices, local_dists, radius, params);
|
||||
for (size_t i = 0; i < local_indices.rows; ++i) {
|
||||
for (size_t j = 0; j < local_indices.cols; ++j) {
|
||||
local_indices[i][j] += offset_;
|
||||
}
|
||||
}
|
||||
SearchResults<DistanceType> local_results;
|
||||
local_results.indices = local_indices;
|
||||
local_results.dists = local_dists;
|
||||
SearchResults<DistanceType> results;
|
||||
|
||||
// perform MPI reduce
|
||||
reduce(world, local_results, results, ResultsMerger<DistanceType>(), 0);
|
||||
|
||||
if (world.rank() == 0) {
|
||||
for (int i = 0; i < std::min(results.indices.rows, indices.rows); ++i) {
|
||||
for (int j = 0; j < std::min(results.indices.cols, indices.cols); ++j) {
|
||||
indices[i][j] = results.indices[i][j];
|
||||
dists[i][j] = results.dists[i][j];
|
||||
}
|
||||
}
|
||||
delete[] results.indices.ptr();
|
||||
delete[] results.dists.ptr();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
} //namespace flann::mpi
|
||||
|
||||
namespace boost { namespace mpi {
|
||||
template<typename DistanceType>
|
||||
struct is_commutative<flann::mpi::ResultsMerger<DistanceType>, flann::mpi::SearchResults<DistanceType> > : mpl::true_ { };
|
||||
} } // end namespace boost::mpi
|
||||
|
||||
|
||||
#endif /* FLANN_MPI_HPP_ */
|
||||
@@ -1,54 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2011 Marius Muja ([email protected]). All rights reserved.
|
||||
* Copyright 2008-2011 David G. Lowe ([email protected]). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef MPI_MATRIX_H_
|
||||
#define MPI_MATRIX_H_
|
||||
|
||||
#include <flann/util/matrix.h>
|
||||
#include <boost/serialization/array.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<class Archive, class T>
|
||||
void serialize(Archive & ar, flann::Matrix<T> & matrix, const unsigned int version)
|
||||
{
|
||||
ar & matrix.rows & matrix.cols & matrix.stride;
|
||||
if (Archive::is_loading::value) {
|
||||
matrix = flann::Matrix<T>(new T[matrix.rows*matrix.cols], matrix.rows, matrix.cols, matrix.stride);
|
||||
}
|
||||
ar & boost::serialization::make_array(matrix.ptr(), matrix.rows*matrix.cols);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* MPI_MATRIX_H_ */
|
||||
@@ -1,103 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2011 Marius Muja ([email protected]). All rights reserved.
|
||||
* Copyright 2008-2011 David G. Lowe ([email protected]). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef MPI_QUERIES_H_
|
||||
#define MPI_QUERIES_H_
|
||||
|
||||
#include <flann/mpi/matrix.h>
|
||||
#include <boost/archive/binary_iarchive.hpp>
|
||||
#include <boost/archive/binary_oarchive.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
struct Request
|
||||
{
|
||||
flann::Matrix<T> queries;
|
||||
int nn;
|
||||
int checks;
|
||||
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const unsigned int version)
|
||||
{
|
||||
ar & queries & nn & checks;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Response
|
||||
{
|
||||
flann::Matrix<int> indices;
|
||||
flann::Matrix<T> dists;
|
||||
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const unsigned int version)
|
||||
{
|
||||
ar & indices & dists;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
|
||||
template <typename T>
|
||||
void read_object(tcp::socket& sock, T& val)
|
||||
{
|
||||
uint32_t size;
|
||||
boost::asio::read(sock, boost::asio::buffer(&size, sizeof(size)));
|
||||
size = ntohl(size);
|
||||
|
||||
boost::asio::streambuf archive_stream;
|
||||
boost::asio::read(sock, archive_stream, boost::asio::transfer_at_least(size));
|
||||
|
||||
boost::archive::binary_iarchive archive(archive_stream);
|
||||
archive >> val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_object(tcp::socket& sock, const T& val)
|
||||
{
|
||||
boost::asio::streambuf archive_stream;
|
||||
boost::archive::binary_oarchive archive(archive_stream);
|
||||
archive << val;
|
||||
|
||||
uint32_t size = archive_stream.size();
|
||||
size = htonl(size);
|
||||
boost::asio::write(sock, boost::asio::buffer(&size, sizeof(size)));
|
||||
boost::asio::write(sock, archive_stream);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* MPI_QUERIES_H_ */
|
||||
@@ -1,153 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2011 Marius Muja ([email protected]). All rights reserved.
|
||||
* Copyright 2008-2011 David G. Lowe ([email protected]). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef MPI_SERVER_H_
|
||||
#define MPI_SERVER_H_
|
||||
|
||||
#include <flann/mpi/index.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#include "queries.h"
|
||||
|
||||
namespace flann {
|
||||
|
||||
namespace mpi {
|
||||
|
||||
template<typename Distance>
|
||||
class Server
|
||||
{
|
||||
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
typedef boost::shared_ptr<tcp::socket> socket_ptr;
|
||||
typedef flann::mpi::Index<Distance> FlannIndex;
|
||||
|
||||
void session(socket_ptr sock)
|
||||
{
|
||||
boost::mpi::communicator world;
|
||||
try {
|
||||
Request<ElementType> req;
|
||||
if (world.rank()==0) {
|
||||
read_object(*sock,req);
|
||||
std::cout << "Received query\n";
|
||||
}
|
||||
// broadcast request to all MPI processes
|
||||
boost::mpi::broadcast(world, req, 0);
|
||||
|
||||
Response<DistanceType> resp;
|
||||
if (world.rank()==0) {
|
||||
int rows = req.queries.rows;
|
||||
int cols = req.nn;
|
||||
resp.indices = flann::Matrix<int>(new int[rows*cols], rows, cols);
|
||||
resp.dists = flann::Matrix<DistanceType>(new DistanceType[rows*cols], rows, cols);
|
||||
}
|
||||
|
||||
std::cout << "Searching in process " << world.rank() << "\n";
|
||||
index_->knnSearch(req.queries, resp.indices, resp.dists, req.nn, flann::SearchParams(req.checks));
|
||||
|
||||
if (world.rank()==0) {
|
||||
std::cout << "Sending result\n";
|
||||
write_object(*sock,resp);
|
||||
}
|
||||
|
||||
delete[] req.queries.ptr();
|
||||
if (world.rank()==0) {
|
||||
delete[] resp.indices.ptr();
|
||||
delete[] resp.dists.ptr();
|
||||
}
|
||||
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
std::cerr << "Exception in thread: " << e.what() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
Server(const std::string& filename, const std::string& dataset, short port, const IndexParams& params) :
|
||||
port_(port)
|
||||
{
|
||||
boost::mpi::communicator world;
|
||||
if (world.rank()==0) {
|
||||
std::cout << "Reading dataset and building index...";
|
||||
std::flush(std::cout);
|
||||
}
|
||||
index_ = new FlannIndex(filename, dataset, params);
|
||||
index_->buildIndex();
|
||||
world.barrier(); // wait for data to be loaded and indexes to be created
|
||||
if (world.rank()==0) {
|
||||
std::cout << "done.\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void run()
|
||||
{
|
||||
boost::mpi::communicator world;
|
||||
boost::shared_ptr<boost::asio::io_service> io_service;
|
||||
boost::shared_ptr<tcp::acceptor> acceptor;
|
||||
|
||||
if (world.rank()==0) {
|
||||
io_service.reset(new boost::asio::io_service());
|
||||
acceptor.reset(new tcp::acceptor(*io_service, tcp::endpoint(tcp::v4(), port_)));
|
||||
std::cout << "Start listening for queries...\n";
|
||||
}
|
||||
for (;;) {
|
||||
socket_ptr sock;
|
||||
if (world.rank()==0) {
|
||||
sock.reset(new tcp::socket(*io_service));
|
||||
acceptor->accept(*sock);
|
||||
std::cout << "Accepted connection\n";
|
||||
}
|
||||
world.barrier(); // everybody waits here for a connection
|
||||
boost::thread t(boost::bind(&Server::session, this, sock));
|
||||
t.join();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
FlannIndex* index_;
|
||||
short port_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mpi
|
||||
} // namespace flann
|
||||
|
||||
#endif // MPI_SERVER_H_
|
||||
@@ -1,139 +0,0 @@
|
||||
#ifndef FLANN_UTIL_CUDA_HEAP_H
|
||||
#define FLANN_UTIL_CUDA_HEAP_H
|
||||
|
||||
/*
|
||||
Copyright (c) 2011, Andreas Mützel <[email protected]>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY Andreas Mützel <[email protected]> ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL Andreas Mützel <[email protected]> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace flann
|
||||
{
|
||||
namespace cuda
|
||||
{
|
||||
template <class T>
|
||||
__device__ __host__ void swap( T& x, T& y )
|
||||
{
|
||||
T t=x;
|
||||
x=y;
|
||||
y=t;
|
||||
}
|
||||
|
||||
namespace heap
|
||||
{
|
||||
|
||||
//! moves an element down the heap until all children are smaller than the element
|
||||
//! if c is a less-than comparator, it do this until all children are larger
|
||||
template <class GreaterThan, class RandomAccessIterator>
|
||||
__host__ __device__ void
|
||||
sift_down( RandomAccessIterator array, size_t begin, size_t length, GreaterThan c = GreaterThan() )
|
||||
{
|
||||
|
||||
while( 2*begin+1 < length ) {
|
||||
size_t left = 2*begin+1;
|
||||
size_t right = 2*begin+2;
|
||||
size_t largest=begin;
|
||||
if((left < length)&& c(array[left], array[largest]) ) largest=left;
|
||||
|
||||
if((right < length)&& c(array[right], array[largest]) ) largest=right;
|
||||
|
||||
if( largest != begin ) {
|
||||
cuda::swap( array[begin], array[largest] );
|
||||
begin=largest;
|
||||
}
|
||||
else return;
|
||||
}
|
||||
}
|
||||
|
||||
//! creates a max-heap in the array beginning at begin of length "length"
|
||||
//! if c is a less-than comparator, it will create a min-heap
|
||||
template <class GreaterThan, class RandomAccessIterator>
|
||||
__host__ __device__ void
|
||||
make_heap( RandomAccessIterator begin, size_t length, GreaterThan c = GreaterThan() )
|
||||
{
|
||||
int i=length/2-1;
|
||||
while( i>=0 ) {
|
||||
sift_down( begin, i, length, c );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! verifies if the array is a max-heap
|
||||
//! if c is a less-than comparator, it will verify if it is a min-heap
|
||||
template <class GreaterThan, class RandomAccessIterator>
|
||||
__host__ __device__ bool
|
||||
is_heap( RandomAccessIterator begin, size_t length, GreaterThan c = GreaterThan() )
|
||||
{
|
||||
for( unsigned i=0; i<length; i++ ) {
|
||||
if((2*i+1 < length)&& c(begin[2*i+1],begin[i]) ) return false;
|
||||
if((2*i+2 < length)&& c(begin[2*i+2],begin[i]) ) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! moves an element down the heap until all children are smaller than the element
|
||||
//! if c is a less-than comparator, it do this until all children are larger
|
||||
template <class GreaterThan, class RandomAccessIterator, class RandomAccessIterator2>
|
||||
__host__ __device__ void
|
||||
sift_down( RandomAccessIterator key, RandomAccessIterator2 value, size_t begin, size_t length, GreaterThan c = GreaterThan() )
|
||||
{
|
||||
|
||||
while( 2*begin+1 < length ) {
|
||||
size_t left = 2*begin+1;
|
||||
size_t right = 2*begin+2;
|
||||
size_t largest=begin;
|
||||
if((left < length)&& c(key[left], key[largest]) ) largest=left;
|
||||
|
||||
if((right < length)&& c(key[right], key[largest]) ) largest=right;
|
||||
|
||||
if( largest != begin ) {
|
||||
cuda::swap( key[begin], key[largest] );
|
||||
cuda::swap( value[begin], value[largest] );
|
||||
begin=largest;
|
||||
}
|
||||
else return;
|
||||
}
|
||||
}
|
||||
|
||||
//! creates a max-heap in the array beginning at begin of length "length"
|
||||
//! if c is a less-than comparator, it will create a min-heap
|
||||
template <class GreaterThan, class RandomAccessIterator, class RandomAccessIterator2>
|
||||
__host__ __device__ void
|
||||
make_heap( RandomAccessIterator key, RandomAccessIterator2 value, size_t length, GreaterThan c = GreaterThan() )
|
||||
{
|
||||
int i=length/2-1;
|
||||
while( i>=0 ) {
|
||||
sift_down( key, value, i, length, c );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,536 +0,0 @@
|
||||
/**********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2011 Andreas Muetzel ([email protected]). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
#ifndef FLANN_UTIL_CUDA_RESULTSET_H
|
||||
#define FLANN_UTIL_CUDA_RESULTSET_H
|
||||
|
||||
#include <flann/util/cuda/heap.h>
|
||||
#include <limits>
|
||||
|
||||
__device__ __forceinline__
|
||||
float infinity()
|
||||
{
|
||||
return __int_as_float(0x7f800000);
|
||||
}
|
||||
|
||||
#ifndef INFINITY
|
||||
#define INFINITY infinity()
|
||||
#endif
|
||||
|
||||
namespace flann
|
||||
{
|
||||
namespace cuda
|
||||
{
|
||||
//! result set for the 1nn search. Doesn't do any global memory accesses on its own,
|
||||
template< typename DistanceType >
|
||||
struct SingleResultSet
|
||||
{
|
||||
int bestIndex;
|
||||
DistanceType bestDist;
|
||||
const DistanceType epsError;
|
||||
|
||||
__device__ __host__
|
||||
SingleResultSet( DistanceType eps ) : bestIndex(-1),bestDist(INFINITY), epsError(eps){ }
|
||||
|
||||
__device__
|
||||
inline float
|
||||
worstDist()
|
||||
{
|
||||
return bestDist;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
insert(int index, DistanceType dist)
|
||||
{
|
||||
if( dist <= bestDist ) {
|
||||
bestIndex=index;
|
||||
bestDist=dist;
|
||||
}
|
||||
}
|
||||
|
||||
DistanceType* resultDist;
|
||||
int* resultIndex;
|
||||
|
||||
__device__
|
||||
inline void
|
||||
setResultLocation( DistanceType* dists, int* index, int thread, int stride )
|
||||
{
|
||||
resultDist=dists+thread*stride;
|
||||
resultIndex=index+thread*stride;
|
||||
if( stride != 1 ) {
|
||||
for( int i=1; i<stride; i++ ) {
|
||||
resultDist[i]=INFINITY;
|
||||
resultIndex[i]=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
finish()
|
||||
{
|
||||
resultDist[0]=bestDist;
|
||||
resultIndex[0]=bestIndex;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename DistanceType >
|
||||
struct GreaterThan
|
||||
{
|
||||
__device__
|
||||
bool operator()(DistanceType a, DistanceType b)
|
||||
{
|
||||
return a>b;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// using this and the template uses 2 or 3 registers more than the direct implementation in the kNearestKernel, but
|
||||
// there is no speed difference.
|
||||
// Setting useHeap as a template parameter leads to a whole lot of things being
|
||||
// optimized away by nvcc.
|
||||
// Register counts are the same as when removing not-needed variables in explicit specializations
|
||||
// and the "if( useHeap )" branches are eliminated at compile time.
|
||||
// The downside of this: a bit more complex kernel launch code.
|
||||
template< typename DistanceType, bool useHeap >
|
||||
struct KnnResultSet
|
||||
{
|
||||
int foundNeighbors;
|
||||
DistanceType largestHeapDist;
|
||||
int maxDistIndex;
|
||||
const int k;
|
||||
const bool sorted;
|
||||
const DistanceType epsError;
|
||||
|
||||
|
||||
__device__ __host__
|
||||
KnnResultSet(int knn, bool sortResults, DistanceType eps) : foundNeighbors(0),largestHeapDist(INFINITY),k(knn), sorted(sortResults), epsError(eps){ }
|
||||
|
||||
// __host__ __device__
|
||||
// KnnResultSet(const KnnResultSet& o):foundNeighbors(o.foundNeighbors),largestHeapDist(o.largestHeapDist),k(o.k){ }
|
||||
|
||||
__device__
|
||||
inline DistanceType
|
||||
worstDist()
|
||||
{
|
||||
return largestHeapDist;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
insert(int index, DistanceType dist)
|
||||
{
|
||||
if( foundNeighbors<k ) {
|
||||
resultDist[foundNeighbors]=dist;
|
||||
resultIndex[foundNeighbors]=index;
|
||||
if( foundNeighbors==k-1) {
|
||||
if( useHeap ) {
|
||||
flann::cuda::heap::make_heap(resultDist,resultIndex,k,GreaterThan<DistanceType>());
|
||||
largestHeapDist=resultDist[0];
|
||||
}
|
||||
else {
|
||||
findLargestDistIndex();
|
||||
}
|
||||
|
||||
}
|
||||
foundNeighbors++;
|
||||
}
|
||||
else if( dist < largestHeapDist ) {
|
||||
if( useHeap ) {
|
||||
resultDist[0]=dist;
|
||||
resultIndex[0]=index;
|
||||
flann::cuda::heap::sift_down(resultDist,resultIndex,0,k,GreaterThan<DistanceType>());
|
||||
largestHeapDist=resultDist[0];
|
||||
}
|
||||
else {
|
||||
resultDist[maxDistIndex]=dist;
|
||||
resultIndex[maxDistIndex]=index;
|
||||
findLargestDistIndex();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
void
|
||||
findLargestDistIndex( )
|
||||
{
|
||||
largestHeapDist=resultDist[0];
|
||||
maxDistIndex=0;
|
||||
for( int i=1; i<k; i++ )
|
||||
if( resultDist[i] > largestHeapDist ) {
|
||||
maxDistIndex=i;
|
||||
largestHeapDist=resultDist[i];
|
||||
}
|
||||
}
|
||||
|
||||
float* resultDist;
|
||||
int* resultIndex;
|
||||
|
||||
__device__
|
||||
inline void
|
||||
setResultLocation( DistanceType* dists, int* index, int thread, int stride )
|
||||
{
|
||||
resultDist=dists+stride*thread;
|
||||
resultIndex=index+stride*thread;
|
||||
for( int i=0; i<stride; i++ ) {
|
||||
resultDist[i]=INFINITY;
|
||||
resultIndex[i]=-1;
|
||||
// resultIndex[tid+i*blockDim.x]=-1;
|
||||
// resultDist[tid+i*blockDim.x]=INFINITY;
|
||||
}
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
inline void
|
||||
finish()
|
||||
{
|
||||
if( sorted ) {
|
||||
if( !useHeap ) flann::cuda::heap::make_heap(resultDist,resultIndex,k,GreaterThan<DistanceType>());
|
||||
for( int i=k-1; i>0; i-- ) {
|
||||
flann::cuda::swap( resultDist[0], resultDist[i] );
|
||||
flann::cuda::swap( resultIndex[0], resultIndex[i] );
|
||||
flann::cuda::heap::sift_down( resultDist,resultIndex, 0, i, GreaterThan<DistanceType>() );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DistanceType>
|
||||
struct CountingRadiusResultSet
|
||||
{
|
||||
int count_;
|
||||
DistanceType radius_sq_;
|
||||
int max_neighbors_;
|
||||
|
||||
__device__ __host__
|
||||
CountingRadiusResultSet(DistanceType radius, int max_neighbors) : count_(0),radius_sq_(radius), max_neighbors_(max_neighbors){ }
|
||||
|
||||
__device__
|
||||
inline DistanceType
|
||||
worstDist()
|
||||
{
|
||||
return radius_sq_;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
insert(int index, float dist)
|
||||
{
|
||||
if( dist < radius_sq_ ) {
|
||||
count_++;
|
||||
}
|
||||
}
|
||||
|
||||
int* resultIndex;
|
||||
|
||||
__device__
|
||||
inline void
|
||||
setResultLocation( DistanceType* /*dists*/, int* count, int thread, int stride )
|
||||
{
|
||||
resultIndex=count+thread*stride;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
finish()
|
||||
{
|
||||
if(( max_neighbors_<=0) ||( count_<=max_neighbors_) ) resultIndex[0]=count_;
|
||||
else resultIndex[0]=max_neighbors_;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename DistanceType, bool useHeap>
|
||||
struct RadiusKnnResultSet
|
||||
{
|
||||
int foundNeighbors;
|
||||
DistanceType largestHeapDist;
|
||||
int maxDistElem;
|
||||
const int k;
|
||||
const bool sorted;
|
||||
const DistanceType radius_sq_;
|
||||
int* segment_starts_;
|
||||
// int count_;
|
||||
|
||||
|
||||
__device__ __host__
|
||||
RadiusKnnResultSet(DistanceType radius, int knn, int* segment_starts, bool sortResults) : foundNeighbors(0),largestHeapDist(radius),k(knn), sorted(sortResults), radius_sq_(radius),segment_starts_(segment_starts) { }
|
||||
|
||||
// __host__ __device__
|
||||
// KnnResultSet(const KnnResultSet& o):foundNeighbors(o.foundNeighbors),largestHeapDist(o.largestHeapDist),k(o.k){ }
|
||||
|
||||
__device__
|
||||
inline DistanceType
|
||||
worstDist()
|
||||
{
|
||||
return largestHeapDist;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
insert(int index, DistanceType dist)
|
||||
{
|
||||
if( dist < radius_sq_ ) {
|
||||
if( foundNeighbors<k ) {
|
||||
resultDist[foundNeighbors]=dist;
|
||||
resultIndex[foundNeighbors]=index;
|
||||
if(( foundNeighbors==k-1) && useHeap) {
|
||||
if( useHeap ) {
|
||||
flann::cuda::heap::make_heap(resultDist,resultIndex,k,GreaterThan<DistanceType>());
|
||||
largestHeapDist=resultDist[0];
|
||||
}
|
||||
else {
|
||||
findLargestDistIndex();
|
||||
}
|
||||
}
|
||||
foundNeighbors++;
|
||||
|
||||
}
|
||||
else if( dist < largestHeapDist ) {
|
||||
if( useHeap ) {
|
||||
resultDist[0]=dist;
|
||||
resultIndex[0]=index;
|
||||
flann::cuda::heap::sift_down(resultDist,resultIndex,0,k,GreaterThan<DistanceType>());
|
||||
largestHeapDist=resultDist[0];
|
||||
}
|
||||
else {
|
||||
resultDist[maxDistElem]=dist;
|
||||
resultIndex[maxDistElem]=index;
|
||||
findLargestDistIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
void
|
||||
findLargestDistIndex( )
|
||||
{
|
||||
largestHeapDist=resultDist[0];
|
||||
maxDistElem=0;
|
||||
for( int i=1; i<k; i++ )
|
||||
if( resultDist[i] > largestHeapDist ) {
|
||||
maxDistElem=i;
|
||||
largestHeapDist=resultDist[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DistanceType* resultDist;
|
||||
int* resultIndex;
|
||||
|
||||
__device__
|
||||
inline void
|
||||
setResultLocation( DistanceType* dists, int* index, int thread, int /*stride*/ )
|
||||
{
|
||||
resultDist=dists+segment_starts_[thread];
|
||||
resultIndex=index+segment_starts_[thread];
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
finish()
|
||||
{
|
||||
if( sorted ) {
|
||||
if( !useHeap ) flann::cuda::heap::make_heap(resultDist,resultIndex,k,GreaterThan<DistanceType>());
|
||||
for( int i=foundNeighbors-1; i>0; i-- ) {
|
||||
flann::cuda::swap( resultDist[0], resultDist[i] );
|
||||
flann::cuda::swap( resultIndex[0], resultIndex[i] );
|
||||
flann::cuda::heap::sift_down( resultDist,resultIndex, 0, i, GreaterThan<DistanceType>() );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Difference to RadiusKnnResultSet: Works like KnnResultSet, doesn't pack the results densely (as the RadiusResultSet does)
|
||||
template <typename DistanceType, bool useHeap>
|
||||
struct KnnRadiusResultSet
|
||||
{
|
||||
int foundNeighbors;
|
||||
DistanceType largestHeapDist;
|
||||
int maxDistIndex;
|
||||
const int k;
|
||||
const bool sorted;
|
||||
const DistanceType epsError;
|
||||
const DistanceType radius_sq;
|
||||
|
||||
|
||||
__device__ __host__
|
||||
KnnRadiusResultSet(int knn, bool sortResults, DistanceType eps, DistanceType radius) : foundNeighbors(0),largestHeapDist(radius),k(knn), sorted(sortResults), epsError(eps),radius_sq(radius){ }
|
||||
|
||||
// __host__ __device__
|
||||
// KnnResultSet(const KnnResultSet& o):foundNeighbors(o.foundNeighbors),largestHeapDist(o.largestHeapDist),k(o.k){ }
|
||||
|
||||
__device__
|
||||
inline DistanceType
|
||||
worstDist()
|
||||
{
|
||||
return largestHeapDist;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
insert(int index, DistanceType dist)
|
||||
{
|
||||
if( dist < largestHeapDist ) {
|
||||
if( foundNeighbors<k ) {
|
||||
resultDist[foundNeighbors]=dist;
|
||||
resultIndex[foundNeighbors]=index;
|
||||
if( foundNeighbors==k-1 ) {
|
||||
if( useHeap ) {
|
||||
flann::cuda::heap::make_heap(resultDist,resultIndex,k,GreaterThan<DistanceType>());
|
||||
largestHeapDist=resultDist[0];
|
||||
}
|
||||
else {
|
||||
findLargestDistIndex();
|
||||
}
|
||||
}
|
||||
foundNeighbors++;
|
||||
}
|
||||
else { //if( dist < largestHeapDist )
|
||||
if( useHeap ) {
|
||||
resultDist[0]=dist;
|
||||
resultIndex[0]=index;
|
||||
flann::cuda::heap::sift_down(resultDist,resultIndex,0,k,GreaterThan<DistanceType>());
|
||||
largestHeapDist=resultDist[0];
|
||||
}
|
||||
else {
|
||||
resultDist[maxDistIndex]=dist;
|
||||
resultIndex[maxDistIndex]=index;
|
||||
findLargestDistIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__device__
|
||||
void
|
||||
findLargestDistIndex( )
|
||||
{
|
||||
largestHeapDist=resultDist[0];
|
||||
maxDistIndex=0;
|
||||
for( int i=1; i<k; i++ )
|
||||
if( resultDist[i] > largestHeapDist ) {
|
||||
maxDistIndex=i;
|
||||
largestHeapDist=resultDist[i];
|
||||
}
|
||||
}
|
||||
|
||||
DistanceType* resultDist;
|
||||
int* resultIndex;
|
||||
|
||||
__device__
|
||||
inline void
|
||||
setResultLocation( DistanceType* dists, int* index, int thread, int stride )
|
||||
{
|
||||
resultDist=dists+stride*thread;
|
||||
resultIndex=index+stride*thread;
|
||||
for( int i=0; i<stride; i++ ) {
|
||||
resultDist[i]=INFINITY;
|
||||
resultIndex[i]=-1;
|
||||
// resultIndex[tid+i*blockDim.x]=-1;
|
||||
// resultDist[tid+i*blockDim.x]=INFINITY;
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
finish()
|
||||
{
|
||||
if( sorted ) {
|
||||
if( !useHeap ) flann::cuda::heap::make_heap(resultDist,resultIndex,k,GreaterThan<DistanceType>());
|
||||
for( int i=k-1; i>0; i-- ) {
|
||||
flann::cuda::swap( resultDist[0], resultDist[i] );
|
||||
flann::cuda::swap( resultIndex[0], resultIndex[i] );
|
||||
flann::cuda::heap::sift_down( resultDist,resultIndex, 0, i, GreaterThan<DistanceType>() );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//! fills the radius output buffer.
|
||||
//! IMPORTANT ASSERTION: ASSUMES THAT THERE IS ENOUGH SPACE FOR EVERY NEIGHBOR! IF THIS ISN'T
|
||||
//! TRUE, USE KnnRadiusResultSet! (Otherwise, the neighbors of one element might overflow into the next element, or past the buffer.)
|
||||
template< typename DistanceType >
|
||||
struct RadiusResultSet
|
||||
{
|
||||
DistanceType radius_sq_;
|
||||
int* segment_starts_;
|
||||
int count_;
|
||||
bool sorted_;
|
||||
|
||||
__device__ __host__
|
||||
RadiusResultSet(DistanceType radius, int* segment_starts, bool sorted) : radius_sq_(radius), segment_starts_(segment_starts), count_(0), sorted_(sorted){ }
|
||||
|
||||
__device__
|
||||
inline DistanceType
|
||||
worstDist()
|
||||
{
|
||||
return radius_sq_;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
insert(int index, DistanceType dist)
|
||||
{
|
||||
if( dist < radius_sq_ ) {
|
||||
resultIndex[count_]=index;
|
||||
resultDist[count_]=dist;
|
||||
count_++;
|
||||
}
|
||||
}
|
||||
|
||||
int* resultIndex;
|
||||
DistanceType* resultDist;
|
||||
|
||||
__device__
|
||||
inline void
|
||||
setResultLocation( DistanceType* dists, int* index, int thread, int /*stride*/ )
|
||||
{
|
||||
resultIndex=index+segment_starts_[thread];
|
||||
resultDist=dists+segment_starts_[thread];
|
||||
}
|
||||
|
||||
__device__
|
||||
inline void
|
||||
finish()
|
||||
{
|
||||
if( sorted_ ) {
|
||||
flann::cuda::heap::make_heap( resultDist,resultIndex, count_, GreaterThan<DistanceType>() );
|
||||
for( int i=count_-1; i>0; i-- ) {
|
||||
flann::cuda::swap( resultDist[0], resultDist[i] );
|
||||
flann::cuda::swap( resultIndex[0], resultIndex[i] );
|
||||
flann::cuda::heap::sift_down( resultDist,resultIndex, 0, i, GreaterThan<DistanceType>() );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
+17
-17
@@ -27,26 +27,26 @@
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef FLANN_ALL_INDICES_H_
|
||||
#define FLANN_ALL_INDICES_H_
|
||||
#ifndef RTABMAP_FLANN_ALL_INDICES_H_
|
||||
#define RTABMAP_FLANN_ALL_INDICES_H_
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "rtflann/general.h"
|
||||
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "flann/algorithms/kdtree_index.h"
|
||||
#include "flann/algorithms/kdtree_single_index.h"
|
||||
#include "flann/algorithms/kmeans_index.h"
|
||||
#include "flann/algorithms/composite_index.h"
|
||||
#include "flann/algorithms/linear_index.h"
|
||||
#include "flann/algorithms/hierarchical_clustering_index.h"
|
||||
#include "flann/algorithms/lsh_index.h"
|
||||
#include "flann/algorithms/autotuned_index.h"
|
||||
#include "rtflann/algorithms/nn_index.h"
|
||||
#include "rtflann/algorithms/kdtree_index.h"
|
||||
#include "rtflann/algorithms/kdtree_single_index.h"
|
||||
#include "rtflann/algorithms/kmeans_index.h"
|
||||
#include "rtflann/algorithms/composite_index.h"
|
||||
#include "rtflann/algorithms/linear_index.h"
|
||||
#include "rtflann/algorithms/hierarchical_clustering_index.h"
|
||||
#include "rtflann/algorithms/lsh_index.h"
|
||||
#include "rtflann/algorithms/autotuned_index.h"
|
||||
#ifdef FLANN_USE_CUDA
|
||||
#include "flann/algorithms/kdtree_cuda_3d_index.h"
|
||||
#include "rtflann/algorithms/kdtree_cuda_3d_index.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -126,14 +126,14 @@ struct valid_combination
|
||||
* Create index
|
||||
**********************************************************/
|
||||
template <template<typename> class Index, typename Distance, typename T>
|
||||
inline NNIndex<Distance>* create_index_(flann::Matrix<T> data, const flann::IndexParams& params, const Distance& distance,
|
||||
inline NNIndex<Distance>* create_index_(rtflann::Matrix<T> data, const rtflann::IndexParams& params, const Distance& distance,
|
||||
typename enable_if<valid_combination<Index,Distance,T>::value,void>::type* = 0)
|
||||
{
|
||||
return new Index<Distance>(data, params, distance);
|
||||
}
|
||||
|
||||
template <template<typename> class Index, typename Distance, typename T>
|
||||
inline NNIndex<Distance>* create_index_(flann::Matrix<T> data, const flann::IndexParams& params, const Distance& distance,
|
||||
inline NNIndex<Distance>* create_index_(rtflann::Matrix<T> data, const rtflann::IndexParams& params, const Distance& distance,
|
||||
typename disable_if<valid_combination<Index,Distance,T>::value,void>::type* = 0)
|
||||
{
|
||||
return NULL;
|
||||
@@ -194,4 +194,4 @@ inline NNIndex<Distance>*
|
||||
|
||||
}
|
||||
|
||||
#endif /* FLANN_ALL_INDICES_H_ */
|
||||
#endif /* RTABMAP_FLANN_ALL_INDICES_H_ */
|
||||
+15
-15
@@ -27,23 +27,23 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
#ifndef FLANN_AUTOTUNED_INDEX_H_
|
||||
#define FLANN_AUTOTUNED_INDEX_H_
|
||||
#ifndef RTABMAP_FLANN_AUTOTUNED_INDEX_H_
|
||||
#define RTABMAP_FLANN_AUTOTUNED_INDEX_H_
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "flann/nn/ground_truth.h"
|
||||
#include "flann/nn/index_testing.h"
|
||||
#include "flann/util/sampling.h"
|
||||
#include "flann/algorithms/kdtree_index.h"
|
||||
#include "flann/algorithms/kdtree_single_index.h"
|
||||
#include "flann/algorithms/kmeans_index.h"
|
||||
#include "flann/algorithms/composite_index.h"
|
||||
#include "flann/algorithms/linear_index.h"
|
||||
#include "flann/util/logger.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "rtflann/algorithms/nn_index.h"
|
||||
#include "rtflann/nn/ground_truth.h"
|
||||
#include "rtflann/nn/index_testing.h"
|
||||
#include "rtflann/util/sampling.h"
|
||||
#include "rtflann/algorithms/kdtree_index.h"
|
||||
#include "rtflann/algorithms/kdtree_single_index.h"
|
||||
#include "rtflann/algorithms/kmeans_index.h"
|
||||
#include "rtflann/algorithms/composite_index.h"
|
||||
#include "rtflann/algorithms/linear_index.h"
|
||||
#include "rtflann/util/logger.h"
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
template<typename Distance>
|
||||
@@ -760,4 +760,4 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* FLANN_AUTOTUNED_INDEX_H_ */
|
||||
#endif /* RTABMAP_FLANN_AUTOTUNED_INDEX_H_ */
|
||||
+5
-5
@@ -5,12 +5,12 @@
|
||||
* Author: marius
|
||||
*/
|
||||
|
||||
#ifndef CENTER_CHOOSER_H_
|
||||
#define CENTER_CHOOSER_H_
|
||||
#ifndef RTABMAP_CENTER_CHOOSER_H_
|
||||
#define RTABMAP_CENTER_CHOOSER_H_
|
||||
|
||||
#include <flann/util/matrix.h>
|
||||
#include "rtflann/util/matrix.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
template <typename Distance, typename ElementType>
|
||||
@@ -382,4 +382,4 @@ public:
|
||||
}
|
||||
|
||||
|
||||
#endif /* CENTER_CHOOSER_H_ */
|
||||
#endif /* RTABMAP_CENTER_CHOOSER_H_ */
|
||||
+7
-7
@@ -28,15 +28,15 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_COMPOSITE_INDEX_H_
|
||||
#define FLANN_COMPOSITE_INDEX_H_
|
||||
#ifndef RTABMAP_FLANN_COMPOSITE_INDEX_H_
|
||||
#define RTABMAP_FLANN_COMPOSITE_INDEX_H_
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "flann/algorithms/kdtree_index.h"
|
||||
#include "flann/algorithms/kmeans_index.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "rtflann/algorithms/nn_index.h"
|
||||
#include "rtflann/algorithms/kdtree_index.h"
|
||||
#include "rtflann/algorithms/kmeans_index.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -28,8 +28,8 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_DIST_H_
|
||||
#define FLANN_DIST_H_
|
||||
#ifndef RTABMAP_FLANN_DIST_H_
|
||||
#define RTABMAP_FLANN_DIST_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
@@ -41,10 +41,10 @@ typedef unsigned __int64 uint64_t;
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "flann/defines.h"
|
||||
#include "rtflann/defines.h"
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
+13
-13
@@ -28,8 +28,8 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_
|
||||
#define FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_
|
||||
#ifndef RTABMAP_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_
|
||||
#define RTABMAP_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
@@ -42,18 +42,18 @@
|
||||
#define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "flann/algorithms/dist.h"
|
||||
#include "flann/util/matrix.h"
|
||||
#include "flann/util/result_set.h"
|
||||
#include "flann/util/heap.h"
|
||||
#include "flann/util/allocator.h"
|
||||
#include "flann/util/random.h"
|
||||
#include "flann/util/saving.h"
|
||||
#include "flann/util/serialization.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "rtflann/algorithms/nn_index.h"
|
||||
#include "rtflann/algorithms/dist.h"
|
||||
#include "rtflann/util/matrix.h"
|
||||
#include "rtflann/util/result_set.h"
|
||||
#include "rtflann/util/heap.h"
|
||||
#include "rtflann/util/allocator.h"
|
||||
#include "rtflann/util/random.h"
|
||||
#include "rtflann/util/saving.h"
|
||||
#include "rtflann/util/serialization.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
struct HierarchicalClusteringIndexParams : public IndexParams
|
||||
+12
-12
@@ -28,8 +28,8 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_KDTREE_INDEX_H_
|
||||
#define FLANN_KDTREE_INDEX_H_
|
||||
#ifndef RTABMAP_FLANN_KDTREE_INDEX_H_
|
||||
#define RTABMAP_FLANN_KDTREE_INDEX_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
@@ -38,18 +38,18 @@
|
||||
#include <stdarg.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "flann/util/dynamic_bitset.h"
|
||||
#include "flann/util/matrix.h"
|
||||
#include "flann/util/result_set.h"
|
||||
#include "flann/util/heap.h"
|
||||
#include "flann/util/allocator.h"
|
||||
#include "flann/util/random.h"
|
||||
#include "flann/util/saving.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "rtflann/algorithms/nn_index.h"
|
||||
#include "rtflann/util/dynamic_bitset.h"
|
||||
#include "rtflann/util/matrix.h"
|
||||
#include "rtflann/util/result_set.h"
|
||||
#include "rtflann/util/heap.h"
|
||||
#include "rtflann/util/allocator.h"
|
||||
#include "rtflann/util/random.h"
|
||||
#include "rtflann/util/saving.h"
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
struct KDTreeIndexParams : public IndexParams
|
||||
+14
-14
@@ -28,24 +28,24 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_KDTREE_SINGLE_INDEX_H_
|
||||
#define FLANN_KDTREE_SINGLE_INDEX_H_
|
||||
#ifndef RTABMAP_FLANN_KDTREE_SINGLE_INDEX_H_
|
||||
#define RTABMAP_FLANN_KDTREE_SINGLE_INDEX_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "flann/util/matrix.h"
|
||||
#include "flann/util/result_set.h"
|
||||
#include "flann/util/heap.h"
|
||||
#include "flann/util/allocator.h"
|
||||
#include "flann/util/random.h"
|
||||
#include "flann/util/saving.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "rtflann/algorithms/nn_index.h"
|
||||
#include "rtflann/util/matrix.h"
|
||||
#include "rtflann/util/result_set.h"
|
||||
#include "rtflann/util/heap.h"
|
||||
#include "rtflann/util/allocator.h"
|
||||
#include "rtflann/util/random.h"
|
||||
#include "rtflann/util/saving.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
struct KDTreeSingleIndexParams : public IndexParams
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
root_bbox_(other.root_bbox_)
|
||||
{
|
||||
if (reorder_) {
|
||||
data_ = flann::Matrix<ElementType>(new ElementType[size_*veclen_], size_, veclen_);
|
||||
data_ = rtflann::Matrix<ElementType>(new ElementType[size_*veclen_], size_, veclen_);
|
||||
std::copy(other.data_[0], other.data_[0]+size_*veclen_, data_[0]);
|
||||
}
|
||||
copyTree(root_node_, other.root_node_);
|
||||
@@ -248,7 +248,7 @@ protected:
|
||||
root_node_ = divideTree(0, size_, root_bbox_ ); // construct the tree
|
||||
|
||||
if (reorder_) {
|
||||
data_ = flann::Matrix<ElementType>(new ElementType[size_*veclen_], size_, veclen_);
|
||||
data_ = rtflann::Matrix<ElementType>(new ElementType[size_*veclen_], size_, veclen_);
|
||||
for (size_t i=0; i<size_; ++i) {
|
||||
std::copy(points_[vind_[i]], points_[vind_[i]]+veclen_, data_[i]);
|
||||
}
|
||||
@@ -342,7 +342,7 @@ private:
|
||||
{
|
||||
if (data_.ptr()) {
|
||||
delete[] data_.ptr();
|
||||
data_ = flann::Matrix<ElementType>();
|
||||
data_ = rtflann::Matrix<ElementType>();
|
||||
}
|
||||
if (root_node_) root_node_->~Node();
|
||||
pool_.free();
|
||||
+14
-14
@@ -28,8 +28,8 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_KMEANS_INDEX_H_
|
||||
#define FLANN_KMEANS_INDEX_H_
|
||||
#ifndef RTABMAP_FLANN_KMEANS_INDEX_H_
|
||||
#define RTABMAP_FLANN_KMEANS_INDEX_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
@@ -38,21 +38,21 @@
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "flann/algorithms/dist.h"
|
||||
#include <flann/algorithms/center_chooser.h>
|
||||
#include "flann/util/matrix.h"
|
||||
#include "flann/util/result_set.h"
|
||||
#include "flann/util/heap.h"
|
||||
#include "flann/util/allocator.h"
|
||||
#include "flann/util/random.h"
|
||||
#include "flann/util/saving.h"
|
||||
#include "flann/util/logger.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "rtflann/algorithms/nn_index.h"
|
||||
#include "rtflann/algorithms/dist.h"
|
||||
#include "rtflann/algorithms/center_chooser.h"
|
||||
#include "rtflann/util/matrix.h"
|
||||
#include "rtflann/util/result_set.h"
|
||||
#include "rtflann/util/heap.h"
|
||||
#include "rtflann/util/allocator.h"
|
||||
#include "rtflann/util/random.h"
|
||||
#include "rtflann/util/saving.h"
|
||||
#include "rtflann/util/logger.h"
|
||||
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
struct KMeansIndexParams : public IndexParams
|
||||
+5
-5
@@ -28,13 +28,13 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_LINEAR_INDEX_H_
|
||||
#define FLANN_LINEAR_INDEX_H_
|
||||
#ifndef RTABMAP_FLANN_LINEAR_INDEX_H_
|
||||
#define RTABMAP_FLANN_LINEAR_INDEX_H_
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "nn_index.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
struct LinearIndexParams : public IndexParams
|
||||
+12
-12
@@ -32,8 +32,8 @@
|
||||
* Author: Vincent Rabaud
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_LSH_INDEX_H_
|
||||
#define FLANN_LSH_INDEX_H_
|
||||
#ifndef RTABMAP_FLANN_LSH_INDEX_H_
|
||||
#define RTABMAP_FLANN_LSH_INDEX_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@@ -41,17 +41,17 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "flann/util/matrix.h"
|
||||
#include "flann/util/result_set.h"
|
||||
#include "flann/util/heap.h"
|
||||
#include "flann/util/lsh_table.h"
|
||||
#include "flann/util/allocator.h"
|
||||
#include "flann/util/random.h"
|
||||
#include "flann/util/saving.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "rtflann/algorithms/nn_index.h"
|
||||
#include "rtflann/util/matrix.h"
|
||||
#include "rtflann/util/result_set.h"
|
||||
#include "rtflann/util/heap.h"
|
||||
#include "rtflann/util/lsh_table.h"
|
||||
#include "rtflann/util/allocator.h"
|
||||
#include "rtflann/util/random.h"
|
||||
#include "rtflann/util/saving.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
struct LshIndexParams : public IndexParams
|
||||
+11
-11
@@ -28,19 +28,19 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_NNINDEX_H
|
||||
#define FLANN_NNINDEX_H
|
||||
#ifndef RTABMAP_FLANN_NNINDEX_H
|
||||
#define RTABMAP_FLANN_NNINDEX_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/util/matrix.h"
|
||||
#include "flann/util/params.h"
|
||||
#include "flann/util/result_set.h"
|
||||
#include "flann/util/dynamic_bitset.h"
|
||||
#include "flann/util/saving.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "rtflann/util/matrix.h"
|
||||
#include "rtflann/util/params.h"
|
||||
#include "rtflann/util/result_set.h"
|
||||
#include "rtflann/util/dynamic_bitset.h"
|
||||
#include "rtflann/util/saving.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
#define KNN_HEAP_THRESHOLD 250
|
||||
@@ -371,7 +371,7 @@ public:
|
||||
size_t knn,
|
||||
const SearchParams& params) const
|
||||
{
|
||||
flann::Matrix<size_t> indices_(new size_t[indices.rows*indices.cols], indices.rows, indices.cols);
|
||||
rtflann::Matrix<size_t> indices_(new size_t[indices.rows*indices.cols], indices.rows, indices.cols);
|
||||
int result = knnSearch(queries, indices_, dists, knn, params);
|
||||
|
||||
for (size_t i=0;i<indices.rows;++i) {
|
||||
@@ -577,7 +577,7 @@ public:
|
||||
float radius,
|
||||
const SearchParams& params) const
|
||||
{
|
||||
flann::Matrix<size_t> indices_(new size_t[indices.rows*indices.cols], indices.rows, indices.cols);
|
||||
rtflann::Matrix<size_t> indices_(new size_t[indices.rows*indices.cols], indices.rows, indices.cols);
|
||||
int result = radiusSearch(queries, indices_, dists, radius, params);
|
||||
|
||||
for (size_t i=0;i<indices.rows;++i) {
|
||||
@@ -27,12 +27,12 @@
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef FLANN_CONFIG_H_
|
||||
#define FLANN_CONFIG_H_
|
||||
#ifndef RTABMAP_FLANN_CONFIG_H_
|
||||
#define RTABMAP_FLANN_CONFIG_H_
|
||||
|
||||
#ifdef FLANN_VERSION_
|
||||
#undef FLANN_VERSION_
|
||||
#endif
|
||||
#define FLANN_VERSION_ "1.8.4"
|
||||
|
||||
#endif /* FLANN_CONFIG_H_ */
|
||||
#endif /* RTABMAP_FLANN_CONFIG_H_ */
|
||||
@@ -26,8 +26,8 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_DEFINES_H_
|
||||
#define FLANN_DEFINES_H_
|
||||
#ifndef RTABMAP_FLANN_DEFINES_H_
|
||||
#define RTABMAP_FLANN_DEFINES_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -71,9 +71,9 @@
|
||||
#undef FLANN_ARRAY_LEN
|
||||
#define FLANN_ARRAY_LEN(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace flann {
|
||||
#endif
|
||||
//#ifdef __cplusplus
|
||||
namespace rtflann {
|
||||
//#endif
|
||||
|
||||
/* Nearest neighbour index algorithms */
|
||||
enum flann_algorithm_t
|
||||
@@ -148,9 +148,9 @@ enum flann_checks_t {
|
||||
FLANN_CHECKS_AUTOTUNED = -2,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
//#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
|
||||
#endif /* FLANN_DEFINES_H_ */
|
||||
#endif /* RTABMAP_FLANN_DEFINES_H_ */
|
||||
@@ -28,8 +28,8 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_HPP_
|
||||
#define FLANN_HPP_
|
||||
#ifndef RTABMAP_FLANN_HPP_
|
||||
#define RTABMAP_FLANN_HPP_
|
||||
|
||||
|
||||
#include <vector>
|
||||
@@ -37,14 +37,14 @@
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/util/matrix.h"
|
||||
#include "flann/util/params.h"
|
||||
#include "flann/util/saving.h"
|
||||
#include "general.h"
|
||||
#include "util/matrix.h"
|
||||
#include "util/params.h"
|
||||
#include "util/saving.h"
|
||||
|
||||
#include "flann/algorithms/all_indices.h"
|
||||
#include "algorithms/all_indices.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -432,4 +432,4 @@ int hierarchicalClustering(const Matrix<typename Distance::ElementType>& points,
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* FLANN_HPP_ */
|
||||
#endif /* RTABMAP_FLANN_HPP_ */
|
||||
@@ -28,15 +28,15 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_GENERAL_H_
|
||||
#define FLANN_GENERAL_H_
|
||||
#ifndef RTABMAP_FLANN_GENERAL_H_
|
||||
#define RTABMAP_FLANN_GENERAL_H_
|
||||
|
||||
#include "defines.h"
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <limits.h>
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
class FLANNException : public std::runtime_error
|
||||
@@ -224,4 +224,4 @@ inline size_t flann_datatype_size(flann_datatype_t type)
|
||||
}
|
||||
|
||||
|
||||
#endif /* FLANN_GENERAL_H_ */
|
||||
#endif /* RTABMAP_FLANN_GENERAL_H_ */
|
||||
@@ -28,14 +28,14 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_GROUND_TRUTH_H_
|
||||
#define FLANN_GROUND_TRUTH_H_
|
||||
#ifndef RTABMAP_FLANN_GROUND_TRUTH_H_
|
||||
#define RTABMAP_FLANN_GROUND_TRUTH_H_
|
||||
|
||||
#include "flann/algorithms/dist.h"
|
||||
#include "flann/util/matrix.h"
|
||||
#include "rtflann/algorithms/dist.h"
|
||||
#include "rtflann/util/matrix.h"
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
template <typename Distance>
|
||||
@@ -28,21 +28,21 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_INDEX_TESTING_H_
|
||||
#define FLANN_INDEX_TESTING_H_
|
||||
#ifndef RTABMAP_FLANN_INDEX_TESTING_H_
|
||||
#define RTABMAP_FLANN_INDEX_TESTING_H_
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include "flann/util/matrix.h"
|
||||
#include "flann/algorithms/nn_index.h"
|
||||
#include "flann/util/result_set.h"
|
||||
#include "flann/util/logger.h"
|
||||
#include "flann/util/timer.h"
|
||||
#include "rtflann/util/matrix.h"
|
||||
#include "rtflann/algorithms/nn_index.h"
|
||||
#include "rtflann/util/result_set.h"
|
||||
#include "rtflann/util/logger.h"
|
||||
#include "rtflann/util/timer.h"
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
inline int countCorrectMatches(size_t* neighbors, size_t* groundTruth, int n)
|
||||
@@ -28,10 +28,10 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_SIMPLEX_DOWNHILL_H_
|
||||
#define FLANN_SIMPLEX_DOWNHILL_H_
|
||||
#ifndef RTABMAP_FLANN_SIMPLEX_DOWNHILL_H_
|
||||
#define RTABMAP_FLANN_SIMPLEX_DOWNHILL_H_
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -28,14 +28,14 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_ALLOCATOR_H_
|
||||
#define FLANN_ALLOCATOR_H_
|
||||
#ifndef RTABMAP_FLANN_ALLOCATOR_H_
|
||||
#define RTABMAP_FLANN_ALLOCATOR_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -194,7 +194,7 @@ public:
|
||||
|
||||
}
|
||||
|
||||
inline void* operator new (std::size_t size, flann::PooledAllocator& allocator)
|
||||
inline void* operator new (std::size_t size, rtflann::PooledAllocator& allocator)
|
||||
{
|
||||
return allocator.allocateMemory(size) ;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef FLANN_ANY_H_
|
||||
#define FLANN_ANY_H_
|
||||
#ifndef RTABMAP_FLANN_ANY_H_
|
||||
#define RTABMAP_FLANN_ANY_H_
|
||||
/*
|
||||
* (C) Copyright Christopher Diggins 2005-2011
|
||||
* (C) Copyright Pablo Aguilar 2005
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <ostream>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
namespace anyimpl
|
||||
@@ -32,8 +32,8 @@
|
||||
* Author: Vincent Rabaud
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_DYNAMIC_BITSET_H_
|
||||
#define FLANN_DYNAMIC_BITSET_H_
|
||||
#ifndef RTABMAP_FLANN_DYNAMIC_BITSET_H_
|
||||
#define RTABMAP_FLANN_DYNAMIC_BITSET_H_
|
||||
|
||||
//#define FLANN_USE_BOOST 1
|
||||
#if FLANN_USE_BOOST
|
||||
@@ -43,7 +43,7 @@ typedef boost::dynamic_bitset<> DynamicBitset;
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
namespace flann {
|
||||
namespace rtflann {
|
||||
|
||||
/** Class re-implementing the boost version of it
|
||||
* This helps not depending on boost, it also does not do the bound checks
|
||||
@@ -28,13 +28,13 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_HEAP_H_
|
||||
#define FLANN_HEAP_H_
|
||||
#ifndef RTABMAP_FLANN_HEAP_H_
|
||||
#define RTABMAP_FLANN_HEAP_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -28,16 +28,16 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_LOGGER_H
|
||||
#define FLANN_LOGGER_H
|
||||
#ifndef RTABMAP_FLANN_LOGGER_H
|
||||
#define RTABMAP_FLANN_LOGGER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "flann/defines.h"
|
||||
#include "rtflann/defines.h"
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
class Logger
|
||||
@@ -134,4 +134,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif //FLANN_LOGGER_H
|
||||
#endif //RTABMAP_FLANN_LOGGER_H
|
||||
@@ -32,8 +32,8 @@
|
||||
* Author: Vincent Rabaud
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_LSH_TABLE_H_
|
||||
#define FLANN_LSH_TABLE_H_
|
||||
#ifndef RTABMAP_FLANN_LSH_TABLE_H_
|
||||
#define RTABMAP_FLANN_LSH_TABLE_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -48,10 +48,10 @@
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "flann/util/dynamic_bitset.h"
|
||||
#include "flann/util/matrix.h"
|
||||
#include "rtflann/util/dynamic_bitset.h"
|
||||
#include "rtflann/util/matrix.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
namespace lsh
|
||||
@@ -28,14 +28,14 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_DATASET_H_
|
||||
#define FLANN_DATASET_H_
|
||||
#ifndef RTABMAP_FLANN_DATASET_H_
|
||||
#define RTABMAP_FLANN_DATASET_H_
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/util/serialization.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "rtflann/util/serialization.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
typedef unsigned char uchar;
|
||||
@@ -28,12 +28,12 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_OBJECT_FACTORY_H_
|
||||
#define FLANN_OBJECT_FACTORY_H_
|
||||
#ifndef RTABMAP_FLANN_OBJECT_FACTORY_H_
|
||||
#define RTABMAP_FLANN_OBJECT_FACTORY_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
class CreatorNotFound
|
||||
@@ -27,16 +27,16 @@
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef FLANN_PARAMS_H_
|
||||
#define FLANN_PARAMS_H_
|
||||
#ifndef RTABMAP_FLANN_PARAMS_H_
|
||||
#define RTABMAP_FLANN_PARAMS_H_
|
||||
|
||||
#include "any.h"
|
||||
#include "flann/general.h"
|
||||
#include "rtflann/util/any.h"
|
||||
#include "rtflann/general.h"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
namespace anyimpl
|
||||
@@ -28,17 +28,17 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_RANDOM_H
|
||||
#define FLANN_RANDOM_H
|
||||
#ifndef RTABMAP_FLANN_RANDOM_H
|
||||
#define RTABMAP_FLANN_RANDOM_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "rtflann/general.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -28,8 +28,8 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_RESULTSET_H
|
||||
#define FLANN_RESULTSET_H
|
||||
#ifndef RTABMAP_FLANN_RESULTSET_H
|
||||
#define RTABMAP_FLANN_RESULTSET_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
/* This record represents a branch point when finding neighbors in
|
||||
@@ -27,13 +27,13 @@
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef FLANN_SAMPLING_H_
|
||||
#define FLANN_SAMPLING_H_
|
||||
#ifndef RTABMAP_FLANN_SAMPLING_H_
|
||||
#define RTABMAP_FLANN_SAMPLING_H_
|
||||
|
||||
#include "flann/util/matrix.h"
|
||||
#include "flann/util/random.h"
|
||||
#include "rtflann/util/matrix.h"
|
||||
#include "rtflann/util/random.h"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
@@ -26,15 +26,15 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_SAVING_H_
|
||||
#define FLANN_SAVING_H_
|
||||
#ifndef RTABMAP_FLANN_SAVING_H_
|
||||
#define RTABMAP_FLANN_SAVING_H_
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "flann/general.h"
|
||||
#include "flann/util/serialization.h"
|
||||
#include "rtflann/general.h"
|
||||
#include "rtflann/util/serialization.h"
|
||||
|
||||
|
||||
#ifdef FLANN_SIGNATURE_
|
||||
@@ -42,7 +42,7 @@
|
||||
#endif
|
||||
#define FLANN_SIGNATURE_ "FLANN_INDEX_v1.1"
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -1,16 +1,16 @@
|
||||
#ifndef SERIALIZATION_H_
|
||||
#define SERIALIZATION_H_
|
||||
#ifndef RTABMAP_SERIALIZATION_H_
|
||||
#define RTABMAP_SERIALIZATION_H_
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
#include "flann/ext/lz4.h"
|
||||
#include "flann/ext/lz4hc.h"
|
||||
#include "rtflann/ext/lz4.h"
|
||||
#include "rtflann/ext/lz4hc.h"
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
struct IndexHeaderStruct {
|
||||
char signature[24];
|
||||
@@ -28,13 +28,13 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef FLANN_TIMER_H
|
||||
#define FLANN_TIMER_H
|
||||
#ifndef RTABMAP_FLANN_TIMER_H
|
||||
#define RTABMAP_FLANN_TIMER_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
||||
namespace flann
|
||||
namespace rtflann
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -491,10 +491,6 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
||||
_ui->comboBox_dictionary_strategy->setObjectName(Parameters::kKpNNStrategy().c_str());
|
||||
_ui->checkBox_dictionary_incremental->setObjectName(Parameters::kKpIncrementalDictionary().c_str());
|
||||
_ui->checkBox_kp_incrementalFlann->setObjectName(Parameters::kKpIncrementalFlann().c_str());
|
||||
#ifndef WITH_FLANN18
|
||||
_ui->checkBox_kp_incrementalFlann->setEnabled(false);
|
||||
_ui->checkBox_kp_incrementalFlann->setChecked(false);
|
||||
#endif
|
||||
_ui->comboBox_detector_strategy->setObjectName(Parameters::kKpDetectorStrategy().c_str());
|
||||
_ui->surf_doubleSpinBox_nndrRatio->setObjectName(Parameters::kKpNndrRatio().c_str());
|
||||
_ui->surf_doubleSpinBox_maxDepth->setObjectName(Parameters::kKpMaxDepth().c_str());
|
||||
|
||||
Reference in New Issue
Block a user