Renamed all flann headers to avoid conflicts if flann is already installed on the computer

This commit is contained in:
matlabbe
2015-09-12 01:36:17 -04:00
parent cf0d781020
commit a45aa5d8f7
61 changed files with 266 additions and 7186 deletions
-6
View File
@@ -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)
+2 -2
View File
@@ -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
)
+34 -34
View File
@@ -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
-38
View File
@@ -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
-609
View File
@@ -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_*/
-30
View File
@@ -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"
-231
View File
@@ -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_ */
-89
View File
@@ -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;
}
-271
View File
@@ -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_ */
-54
View File
@@ -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_ */
-103
View File
@@ -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_ */
-153
View File
@@ -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_
-139
View File
@@ -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
-536
View File
@@ -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
@@ -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_ */
@@ -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,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_ */
@@ -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>
@@ -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
@@ -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
@@ -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();
@@ -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
@@ -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
@@ -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
@@ -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
{
/**
-4
View File
@@ -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());