提交 0550a128 编写于 作者: M Marius Muja

Using struct for SearchParams instead of map<string,any> for better efficiency

上级 1b356b92
......@@ -746,7 +746,7 @@ flann::Matrix<int> indices_gpu(gpu_pointer_indices,n_points, knn, stride);
flann::Matrix<float> dists_gpu(gpu_pointer_dists,n_points, knn, stride);
flann::SearchParams params;
params["matrices_in_gpu_ram"]=true;
params.matrices_in_gpu_ram = true;
flannindex.knnSearch( queries_gpu ,indices_gpu,dists_gpu,knn, params);
\end{Verbatim}
......
/***********************************************************************
* Software License Agreement (BSD License)
*
* Copyright 2008-2010 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
* Copyright 2008-2010 David G. Lowe (lowe@cs.ubc.ca). 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 QUERIES_H_
#define QUERIES_H_
#include <flann/util/matrix.h>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.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.data = new T[matrix.rows*matrix.cols];
}
ar & boost::serialization::make_array(matrix.data, matrix.rows*matrix.cols);
}
}
}
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 /* QUERIES_H_ */
......@@ -123,7 +123,7 @@ public:
{
save_value(stream, (int)bestIndex_->getType());
bestIndex_->saveIndex(stream);
save_value(stream, get_param<int>(bestSearchParams_, "checks"));
save_value(stream, bestSearchParams_.checks);
}
/**
......@@ -138,9 +138,7 @@ public:
params["algorithm"] = (flann_algorithm_t)index_type;
bestIndex_ = create_index_by_type<Distance>(dataset_, params, distance_);
bestIndex_->loadIndex(stream);
int checks;
load_value(stream, checks);
bestSearchParams_["checks"] = checks;
load_value(stream, bestSearchParams_.checks);
}
/**
......@@ -148,8 +146,7 @@ public:
*/
virtual void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
{
int checks = get_param(searchParams,"checks",(int)FLANN_CHECKS_AUTOTUNED);
if (checks == FLANN_CHECKS_AUTOTUNED) {
if (searchParams.checks == FLANN_CHECKS_AUTOTUNED) {
bestIndex_->findNeighbors(result, vec, bestSearchParams_);
}
else {
......@@ -540,7 +537,7 @@ private:
}
Logger::info("Required number of checks: %d \n", checks);
searchParams["checks"] = checks;
searchParams.checks = checks;
speedup = linear / searchTime;
......
......@@ -416,7 +416,7 @@ public:
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
{
int maxChecks = get_param(searchParams,"checks",32);
int maxChecks = searchParams.checks;
// Priority queue storing intermediate branches in the best-bin-first search
Heap<BranchSt>* heap = new Heap<BranchSt>(size_);
......
......@@ -280,14 +280,14 @@ void KDTreeCuda3dIndex<Distance>::knnSearchGpu(const Matrix<ElementType>& querie
assert(int(indices.cols) >= knn);
assert( dists.cols == indices.cols && dists.stride==indices.stride );
bool matrices_on_gpu = get_param(params, "matrices_in_gpu_ram", false);
bool matrices_on_gpu = params.matrices_in_gpu_ram;
int threadsPerBlock = 128;
int blocksPerGrid=(queries.rows+threadsPerBlock-1)/threadsPerBlock;
float epsError = 1+get_param(params,"eps",0.0f);
bool sorted = get_param(params,"sorted",true);
bool use_heap = get_param(params,"use_heap",false);
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;
......@@ -437,9 +437,9 @@ int KDTreeCuda3dIndex<Distance >::radiusSearchGpu(const Matrix<ElementType>& que
// assert(indices.roasdfws >= queries.rows);
// assert(dists.rows >= queries.rows);
int max_neighbors = get_param(params, "max_neighbors", -1);
bool sorted = get_param(params, "sorted", true);
bool use_heap = get_param(params, "use_heap", false);
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);
......@@ -506,7 +506,7 @@ int KDTreeCuda3dIndex<Distance >::radiusSearchGpu(const Matrix<ElementType>& que
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]),get_param(params, "sorted", true)), distance);
queries.rows, flann::cuda::RadiusResultSet<float>(radius,thrust::raw_pointer_cast(&countsDev[0]),params.sorted), distance);
}
else {
if( use_heap ) {
......@@ -521,7 +521,7 @@ int KDTreeCuda3dIndex<Distance >::radiusSearchGpu(const Matrix<ElementType>& que
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]),get_param(params, "sorted", true)), distance);
queries.rows, flann::cuda::RadiusKnnResultSet<float, true>(radius,max_neighbors, thrust::raw_pointer_cast(&countsDev[0]),params.sorted), distance);
}
else {
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
......@@ -535,7 +535,7 @@ int KDTreeCuda3dIndex<Distance >::radiusSearchGpu(const Matrix<ElementType>& que
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]),get_param(params, "sorted", true)), distance);
queries.rows, flann::cuda::RadiusKnnResultSet<float, false>(radius,max_neighbors, thrust::raw_pointer_cast(&countsDev[0]),params.sorted), distance);
}
}
thrust::transform(indicesDev.begin(), indicesDev.end(), indicesDev.begin(), map_indices(thrust::raw_pointer_cast( &((*gpu_helper_->gpu_vind_))[0]) ));
......@@ -566,17 +566,17 @@ struct isNotMinusOne
template< typename Distance>
int KDTreeCuda3dIndex< Distance >::radiusSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, float radius, const SearchParams& params)
{
int max_neighbors = get_param(params, "max_neighbors", -1);
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 );
assert(dists.rows >= queries.rows || max_neighbors==0 );
bool sorted = get_param(params, "sorted", true);
bool matrices_on_gpu = get_param(params, "matrices_in_gpu_ram", false);
float epsError = 1+get_param(params,"eps",0.0f);
bool use_heap = get_param(params,"use_heap",false);
bool sorted = params.sorted;
bool matrices_on_gpu = params.matrices_in_gpu_ram;
float epsError = 1+params.eps;
bool use_heap = params.use_heap;
if( max_neighbors<0 ) max_neighbors=indices.cols;
......@@ -610,7 +610,6 @@ int KDTreeCuda3dIndex< Distance >::radiusSearchGpu(const Matrix<ElementType>& qu
thrust::device_vector<float> distsDev(queries.rows* max_neighbors);
thrust::device_vector<int> indicesDev(queries.rows* max_neighbors);
// bool sorted = get_param(params,"sorted",true);
if( use_heap ) {
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
......@@ -675,7 +674,6 @@ int KDTreeCuda3dIndex< Distance >::radiusSearchGpu(const Matrix<ElementType>& qu
thrust::copy( indicesDev.begin(), indicesDev.end(), indices.ptr() );
return thrust::reduce(indicesDev.begin(), indicesDev.end() );
}
// bool sorted = get_param(params,"sorted",true);
if( use_heap ) {
KdTreeCudaPrivate::nearestKernel<<<blocksPerGrid, threadsPerBlock>>> (thrust::raw_pointer_cast(&((*gpu_helper_->gpu_splits_)[0])),
......
......@@ -199,13 +199,7 @@ public:
*/
virtual int knnSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, size_t knn, const SearchParams& params)
{
if( get_param(params,"use_cpu",false) ) {
throw FLANNException( "CPU search not supported!" );
// return NNIndex<Distance>::knnSearch(queries,indices, dists, knn, params);
}
else {
knnSearchGpu(queries,indices, dists, knn, params);
}
return knn*queries.rows; // hack...
}
......@@ -223,13 +217,7 @@ public:
size_t knn,
const SearchParams& params)
{
if( get_param(params,"use_cpu",false) ) {
throw FLANNException( "CPU search not supported!" );
// return NNIndex<Distance>::knnSearch(queries,indices, dists, knn, params);
}
else {
knnSearchGpu(queries,indices, dists, knn, params);
}
return knn*queries.rows; // hack...
}
......@@ -268,26 +256,14 @@ public:
virtual int radiusSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists,
float radius, const SearchParams& params)
{
if( get_param(params,"use_cpu",false) ) {
throw FLANNException( "CPU search not supported!" );
// return NNIndex<Distance>::radiusSearch(queries,indices, dists, radius, params);
}
else {
return radiusSearchGpu(queries,indices, dists, radius, params);
}
}
virtual int radiusSearch(const Matrix<ElementType>& queries, std::vector< std::vector<int> >& indices,
std::vector<std::vector<DistanceType> >& dists, float radius, const SearchParams& params)
{
if( get_param(params,"use_cpu",false) ) {
throw FLANNException( "CPU search not supported!" );
return NNIndex<Distance>::radiusSearch(queries,indices, dists, radius, params);
}
else {
return radiusSearchGpu(queries,indices, dists, radius, params);
}
}
int radiusSearchGpu(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists,
float radius, const SearchParams& params);
......
......@@ -199,8 +199,8 @@ public:
*/
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
{
int maxChecks = get_param(searchParams,"checks", 32);
float epsError = 1+get_param(searchParams,"eps",0.0f);
int maxChecks = searchParams.checks;
float epsError = 1+searchParams.eps;
if (maxChecks==FLANN_CHECKS_UNLIMITED) {
getExactNeighbors(result, vec, epsError);
......
......@@ -213,7 +213,7 @@ public:
*/
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
{
float epsError = 1+get_param(searchParams,"eps",0.0f);
float epsError = 1+searchParams.eps;
std::vector<DistanceType> dists(dim_,0);
DistanceType distsq = computeInitialDistances(vec, dists);
......@@ -517,14 +517,13 @@ private:
{
/* If this is a leaf node, then do check and return. */
if ((node->child1 == NULL)&&(node->child2 == NULL)) {
// DistanceType worst_dist = result_set.worstDist();
DistanceType worst_dist = result_set.worstDist();
for (int i=node->left; i<node->right; ++i) {
int index = reorder_ ? i : vind_[i];
DistanceType dist = distance_(vec, data_[index], dim_);
// DistanceType dist = distance_(vec, data_[index], dim_, worst_dist);
// if (dist<worst_dist) {
DistanceType dist = distance_(vec, data_[index], dim_, worst_dist);
if (dist<worst_dist) {
result_set.addPoint(dist,vind_[i]);
// }
}
}
return;
}
......
......@@ -426,7 +426,7 @@ public:
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
{
int maxChecks = get_param(searchParams,"checks",32);
int maxChecks = searchParams.checks;
if (maxChecks==FLANN_CHECKS_UNLIMITED) {
findExactNN(root_, result, vec);
......
......@@ -196,16 +196,14 @@ public:
assert(dists.rows >= queries.rows);
assert(indices.cols >= knn);
assert(dists.cols >= knn);
bool sorted = get_param(params,"sorted",true);
bool use_heap = get_param(params,"use_heap",false);
int count = 0;
if (use_heap) {
if (params.use_heap==True) {
KNNUniqueResultSet<DistanceType> resultSet(knn);
for (size_t i = 0; i < queries.rows; i++) {
resultSet.clear();
findNeighbors(resultSet, queries[i], params);
resultSet.copy(indices[i], dists[i], knn, sorted);
resultSet.copy(indices[i], dists[i], knn, params.sorted);
count += resultSet.size();
}
}
......@@ -214,7 +212,7 @@ public:
for (size_t i = 0; i < queries.rows; i++) {
resultSet.clear();
findNeighbors(resultSet, queries[i], params);
resultSet.copy(indices[i], dists[i], knn, sorted);
resultSet.copy(indices[i], dists[i], knn, params.sorted);
count += resultSet.size();
}
}
......@@ -237,13 +235,11 @@ public:
const SearchParams& params)
{
assert(queries.cols == veclen());
bool sorted = get_param(params,"sorted",true);
bool use_heap = get_param(params,"use_heap",false);
if (indices.size() < queries.rows ) indices.resize(queries.rows);
if (dists.size() < queries.rows ) dists.resize(queries.rows);
int count = 0;
if (use_heap) {
if (params.use_heap==True) {
KNNUniqueResultSet<DistanceType> resultSet(knn);
for (size_t i = 0; i < queries.rows; i++) {
resultSet.clear();
......@@ -251,7 +247,7 @@ public:
size_t n = std::min(resultSet.size(), knn);
indices[i].resize(n);
dists[i].resize(n);
resultSet.copy(&indices[i][0], &dists[i][0], n, sorted);
resultSet.copy(&indices[i][0], &dists[i][0], n, params.sorted);
count += n;
}
}
......@@ -263,7 +259,7 @@ public:
size_t n = std::min(resultSet.size(), knn);
indices[i].resize(n);
dists[i].resize(n);
resultSet.copy(&indices[i][0], &dists[i][0], n, sorted);
resultSet.copy(&indices[i][0], &dists[i][0], n, params.sorted);
count += n;
}
}
......
......@@ -87,21 +87,19 @@ public:
assert(dists.rows >= queries.rows);
assert(indices.cols >= knn);
assert(dists.cols >= knn);
bool sorted = get_param(params,"sorted",true);
bool use_heap;
if (!has_param(params,"use_heap")) {
if (params.use_heap==Undefined) {
use_heap = (knn>KNN_HEAP_THRESHOLD)?true:false;
}
else {
use_heap = get_param(params,"use_heap",false);
use_heap = (params.use_heap==True)?true:false;
}
int count = 0;
#ifdef TBB
int cores = get_param(params,"cores",1);
assert(cores >= 1 || cores == -1);
// Check if we need to do multicore search or stick with single core FLANN (less overhead)
if(cores == 1)
if(params.cores == 1)
{
#endif
if (use_heap) {
......@@ -109,7 +107,7 @@ public:
for (size_t i = 0; i < queries.rows; i++) {
resultSet.clear();
findNeighbors(resultSet, queries[i], params);
resultSet.copy(indices[i], dists[i], knn, sorted);
resultSet.copy(indices[i], dists[i], knn, params.sorted);
count += resultSet.size();
}
}
......@@ -118,7 +116,7 @@ public:
for (size_t i = 0; i < queries.rows; i++) {
resultSet.clear();
findNeighbors(resultSet, queries[i], params);
resultSet.copy(indices[i], dists[i], knn, sorted);
resultSet.copy(indices[i], dists[i], knn, params.sorted);
count += resultSet.size();
}
}
......@@ -127,7 +125,7 @@ public:
else
{
// Initialise the task scheduler for the use of Intel TBB parallel constructs
tbb::task_scheduler_init task_sched(cores);
tbb::task_scheduler_init task_sched(params.cores);
// Make an atomic integer count, such that we can keep track of amount of neighbors found
tbb::atomic<int> atomic_count;
......@@ -162,13 +160,12 @@ public:
const SearchParams& params)
{
assert(queries.cols == veclen());
bool sorted = get_param(params,"sorted",true);
bool use_heap;
if (!has_param(params,"use_heap")) {
if (params.use_heap==Undefined) {
use_heap = (knn>KNN_HEAP_THRESHOLD)?true:false;
}
else {
use_heap = get_param(params,"use_heap",false);
use_heap = (params.use_heap==True)?true:false;
}
if (indices.size() < queries.rows ) indices.resize(queries.rows);
......@@ -176,10 +173,8 @@ public:
int count = 0;
#ifdef TBB
int cores = get_param(params,"cores",1);
assert(cores >= 1 || cores == -1);
// Check if we need to do multicore search or stick with single core FLANN (less overhead)
if(cores == 1)
if(params.cores == 1)
{
#endif
if (use_heap) {
......@@ -190,7 +185,7 @@ public:
size_t n = std::min(resultSet.size(), knn);
indices[i].resize(n);
dists[i].resize(n);
resultSet.copy(&indices[i][0], &dists[i][0], n, sorted);
resultSet.copy(&indices[i][0], &dists[i][0], n, params.sorted);
count += n;
}
}
......@@ -202,7 +197,7 @@ public:
size_t n = std::min(resultSet.size(), knn);
indices[i].resize(n);
dists[i].resize(n);
resultSet.copy(&indices[i][0], &dists[i][0], n, sorted);
resultSet.copy(&indices[i][0], &dists[i][0], n, params.sorted);
count += n;
}
}
......@@ -211,7 +206,7 @@ public:
else
{
// Initialise the task scheduler for the use of Intel TBB parallel constructs
tbb::task_scheduler_init task_sched(cores);
tbb::task_scheduler_init task_sched(params.cores);
// Make an atomic integer count, such that we can keep track of amount of neighbors found
tbb::atomic<int> atomic_count;
......@@ -245,13 +240,15 @@ public:
assert(queries.cols == veclen());
int count = 0;
#ifdef TBB
int cores = get_param(params,"cores",1);
assert(cores >= 1 || cores == -1);
// Check if we need to do multicore search or stick with single core FLANN (less overhead)
if(cores == 1)
if(params.cores == 1)
{
#endif
int max_neighbors = get_param(params, "max_neighbors", -1);
size_t num_neighbors = std::min(indices.cols, dists.cols);
int max_neighbors = params.max_neighbors;
if (max_neighbors<0) max_neighbors = num_neighbors;
else max_neighbors = std::min(max_neighbors,(int)num_neighbors);
if (max_neighbors==0) {
CountRadiusResultSet<DistanceType> resultSet(radius);
for (size_t i = 0; i < queries.rows; i++) {
......@@ -261,13 +258,10 @@ public:
}
}
else {
size_t num_neighbors = std::min(indices.cols, dists.cols);
bool sorted = get_param(params, "sorted", true);
bool has_max_neighbors = has_param(params,"max_neighbors");
// explicitly indicated to use unbounded radius result set
// or we know there'll be enough room for resulting indices and dists
if (max_neighbors<0 && (has_max_neighbors || num_neighbors>=size())) {
if (params.max_neighbors<0 && (num_neighbors>=size())) {
RadiusResultSet<DistanceType> resultSet(radius);
for (size_t i = 0; i < queries.rows; i++) {
resultSet.clear();
......@@ -275,7 +269,7 @@ public:
size_t n = resultSet.size();
count += n;
if (n>num_neighbors) n = num_neighbors;
resultSet.copy(indices[i], dists[i], n, sorted);
resultSet.copy(indices[i], dists[i], n, params.sorted);
// mark the next element in the output buffers as unused
if (n<indices.cols) indices[i][n] = -1;
......@@ -283,8 +277,6 @@ public:
}
}
else {
if (max_neighbors<0) max_neighbors = num_neighbors;
else max_neighbors = std::min(max_neighbors,(int)num_neighbors);
// number of neighbors limited to max_neighbors
KNNRadiusResultSet<DistanceType> resultSet(radius, max_neighbors);
for (size_t i = 0; i < queries.rows; i++) {
......@@ -293,7 +285,7 @@ public:
size_t n = resultSet.size();
count += n;
if ((int)n>max_neighbors) n = max_neighbors;
resultSet.copy(indices[i], dists[i], n, sorted);
resultSet.copy(indices[i], dists[i], n, params.sorted);
// mark the next element in the output buffers as unused
if (n<indices.cols) indices[i][n] = -1;
......@@ -306,7 +298,7 @@ public:
else
{
// Initialise the task scheduler for the use of Intel TBB parallel constructs
tbb::task_scheduler_init task_sched(cores);
tbb::task_scheduler_init task_sched(params.cores);
// Make an atomic integer count, such that we can keep track of amount of neighbors found
tbb::atomic<int> atomic_count;
......@@ -330,15 +322,12 @@ public:
assert(queries.cols == veclen());
int count = 0;
#ifdef TBB
int cores = get_param(params,"cores",1);
assert(cores >= 1 || cores == -1);
// Check if we need to do multicore search or stick with single core FLANN (less overhead)
if(cores == 1)
if(params.cores == 1)
{
#endif
int max_neighbors = get_param(params, "max_neighbors", -1);
// just count neighbors
if (max_neighbors==0) {
if (params.max_neighbors==0) {
CountRadiusResultSet<DistanceType> resultSet(radius);
for (size_t i = 0; i < queries.rows; i++) {
resultSet.clear();
......@@ -347,11 +336,10 @@ public:
}
}
else {
bool sorted = get_param(params, "sorted", true);
if (indices.size() < queries.rows ) indices.resize(queries.rows);
if (dists.size() < queries.rows ) dists.resize(queries.rows);
if (max_neighbors<0) {
if (params.max_neighbors<0) {
// search for all neighbors
RadiusResultSet<DistanceType> resultSet(radius);
for (size_t i = 0; i < queries.rows; i++) {
......@@ -361,21 +349,21 @@ public:
count += n;
indices[i].resize(n);
dists[i].resize(n);
resultSet.copy(&indices[i][0], &dists[i][0], n, sorted);
resultSet.copy(&indices[i][0], &dists[i][0], n, params.sorted);
}
}
else {
// number of neighbors limited to max_neighbors
KNNRadiusResultSet<DistanceType> resultSet(radius, max_neighbors);
KNNRadiusResultSet<DistanceType> resultSet(radius, params.max_neighbors);
for (size_t i = 0; i < queries.rows; i++) {
resultSet.clear();
findNeighbors(resultSet, queries[i], params);
size_t n = resultSet.size();
count += n;
if ((int)n>max_neighbors) n = max_neighbors;
if ((int)n>params.max_neighbors) n = params.max_neighbors;
indices[i].resize(n);
dists[i].resize(n);
resultSet.copy(&indices[i][0], &dists[i][0], n, sorted);
resultSet.copy(&indices[i][0], &dists[i][0], n, params.sorted);
}
}
}
......@@ -384,7 +372,7 @@ public:
else
{
// Initialise the task scheduler for the use of Intel TBB parallel constructs
tbb::task_scheduler_init task_sched(cores);
tbb::task_scheduler_init task_sched(params.cores);
// Reset atomic count before passing it on to the threads, such that we can keep track of amount of neighbors found
tbb::atomic<int> atomic_count;
......
......@@ -149,7 +149,7 @@ flann_index_t __flann_build_index(typename Distance::ElementType* dataset, int r
if (index->getType()==FLANN_INDEX_AUTOTUNED) {
AutotunedIndex<Distance>* autotuned_index = (AutotunedIndex<Distance>*)index->getIndex();
// FIXME
flann_params->checks = get_param<int>(autotuned_index->getSearchParameters(),"checks");
flann_params->checks = autotuned_index->getSearchParameters().checks;
*speedup = autotuned_index->getSpeedup();
}
......
......@@ -64,7 +64,7 @@ struct SavedIndexParams : public IndexParams
{
SavedIndexParams(std::string filename)
{
(* this)["algorithm"] = FLANN_INDEX_SAVED;
(*this)["algorithm"] = FLANN_INDEX_SAVED;
(*this)["filename"] = filename;
}
};
......@@ -98,7 +98,7 @@ NNIndex<Distance>* load_saved_index(const Matrix<typename Distance::ElementType>
template<typename Distance>
class Index : public NNIndex<Distance>
class Index
{
public:
typedef typename Distance::ElementType ElementType;
......@@ -277,14 +277,6 @@ public:
return nnIndex_->radiusSearch(queries, indices, dists, radius, params);
}
/**
* \brief Method that searches for nearest-neighbours
*/
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
{
nnIndex_->findNeighbors(result, vec, searchParams);
}
/**
* \brief Returns actual index
*/
......
......@@ -59,7 +59,7 @@ public:
Request<ElementType> req;
req.nn = knn;
req.queries = queries;
req.checks = get_param<int>(params,"checks");
req.checks = params.checks;
// send request
write_object(sock,req);
......
......@@ -79,17 +79,14 @@ public:
*/
void operator()( const tbb::blocked_range<size_t>& r ) const
{
bool sorted = get_param(params_,"sorted",true);
bool use_heap = get_param(params_,"use_heap",false);
if (use_heap)
if (params_.use_heap==True)
{
KNNResultSet2<DistanceType> resultSet(knn_);
for (size_t i=r.begin(); i!=r.end(); ++i)
{
resultSet.clear();
nnIndex_->findNeighbors(resultSet, queries_[i], params_);
resultSet.copy(indices_[i], distances_[i], knn_, sorted);
resultSet.copy(indices_[i], distances_[i], knn_, params_.sorted);
count_ += resultSet.size();
}
}
......@@ -100,7 +97,7 @@ public:
{
resultSet.clear();
nnIndex_->findNeighbors(resultSet, queries_[i], params_);
resultSet.copy(indices_[i], distances_[i], knn_, sorted);
resultSet.copy(indices_[i], distances_[i], knn_, params_.sorted);
count_ += resultSet.size();
}
}
......@@ -172,10 +169,7 @@ public:
*/
void operator()( const tbb::blocked_range<size_t>& r ) const
{
bool sorted = get_param(params_,"sorted",true);
bool use_heap = get_param(params_,"use_heap",false);
if (use_heap) {
if (params_.use_heap==True) {
KNNResultSet2<DistanceType> resultSet(knn_);
for (size_t i=r.begin(); i!=r.end(); ++i)
{
......@@ -184,7 +178,7 @@ public:
size_t n = std::min(resultSet.size(), knn_);
indices_[i].resize(n);
distances_[i].resize(n);
resultSet.copy(&indices_[i][0], &distances_[i][0], n, sorted);
resultSet.copy(&indices_[i][0], &distances_[i][0], n, params_.sorted);
count_ += n;
}
}
......@@ -197,7 +191,7 @@ public:
size_t n = std::min(resultSet.size(), knn_);
indices_[i].resize(n);
distances_[i].resize(n);
resultSet.copy(&indices_[i][0], &distances_[i][0], n, sorted);
resultSet.copy(&indices_[i][0], &distances_[i][0], n, params_.sorted);
count_ += n;
}
}
......@@ -269,7 +263,10 @@ public:
void operator()( const tbb::blocked_range<size_t>& r ) const
{
int max_neighbors = get_param(params_, "max_neighbors", -1);
size_t num_neighbors = std::min(indices_.cols, distances_.cols);
int max_neighbors = params_.max_neighbors;
if (max_neighbors<0) max_neighbors = num_neighbors;
else max_neighbors = std::min(max_neighbors,(int)num_neighbors);
if (max_neighbors==0) {
CountRadiusResultSet<DistanceType> resultSet(radius_);
......@@ -281,13 +278,10 @@ public:
}
}
else {
size_t num_neighbors = std::min(indices_.cols, distances_.cols);
bool sorted = get_param(params_, "sorted", true);
bool has_max_neighbors = has_param(params_,"max_neighbors");
// explicitly indicated to use unbounded radius result set
// or we know there'll be enough room for resulting indices and dists
if (max_neighbors<0 && (has_max_neighbors || num_neighbors>=nnIndex_->size())) {
if (params_.max_neighbors<0 && (num_neighbors>=nnIndex_->size())) {
RadiusResultSet<DistanceType> resultSet(radius_);
for (size_t i=r.begin(); i!=r.end(); ++i)
{
......@@ -296,7 +290,7 @@ public:
size_t n = resultSet.size();
count_ += n;
if (n>num_neighbors) n = num_neighbors;
resultSet.copy(indices_[i], distances_[i], n, sorted);
resultSet.copy(indices_[i], distances_[i], n, params_.sorted);
// mark the next element in the output buffers as unused
if (n<indices_.cols) indices_[i][n] = -1;
......@@ -304,8 +298,6 @@ public:
}
}
else {
if (max_neighbors<0) max_neighbors = num_neighbors;
else max_neighbors = std::min(max_neighbors,(int)num_neighbors);
// number of neighbors limited to max_neighbors
KNNRadiusResultSet<DistanceType> resultSet(radius_, max_neighbors);
for (size_t i=r.begin(); i!=r.end(); ++i)
......@@ -315,7 +307,7 @@ public:
size_t n = resultSet.size();
count_ += n ;
if ((int)n>max_neighbors) n = max_neighbors;
resultSet.copy(indices_[i], distances_[i], n, sorted);
resultSet.copy(indices_[i], distances_[i], n, params_.sorted);
// mark the next element in the output buffers as unused
if (n<indices_.cols) indices_[i][n] = -1;
......@@ -391,8 +383,7 @@ public:
void operator()( const tbb::blocked_range<size_t>& r ) const
{
int max_neighbors = get_param(params_, "max_neighbors", -1);
int max_neighbors = params_.max_neighbors;
// just count neighbors
if (max_neighbors==0) {
CountRadiusResultSet<DistanceType> resultSet(radius_);
......@@ -404,7 +395,6 @@ public:
}
}
else {
bool sorted = get_param(params_, "sorted", true);
if (indices_.size() < queries_.rows ) indices_.resize(queries_.rows);
if (distances_.size() < queries_.rows ) distances_.resize(queries_.rows);
......@@ -419,12 +409,12 @@ public:
count_ += n;
indices_[i].resize(n);
distances_[i].resize(n);
resultSet.copy(&indices_[i][0], &distances_[i][0], n, sorted);
resultSet.copy(&indices_[i][0], &distances_[i][0], n, params_.sorted);
}
}
else {
// number of neighbors limited to max_neighbors
KNNRadiusResultSet<DistanceType> resultSet(radius_, max_neighbors);
KNNRadiusResultSet<DistanceType> resultSet(radius_, params_.max_neighbors);
for (size_t i=r.begin(); i!=r.end(); ++i)
{
resultSet.clear();
......@@ -434,7 +424,7 @@ public:
if ((int)n>max_neighbors) n = max_neighbors;
indices_[i].resize(n);
distances_[i].resize(n);
resultSet.copy(&indices_[i][0], &distances_[i][0], n, sorted);
resultSet.copy(&indices_[i][0], &distances_[i][0], n, params_.sorted);
}
}
}
......
......@@ -41,21 +41,39 @@ namespace flann
typedef std::map<std::string, any> IndexParams;
struct SearchParams : public IndexParams
{
SearchParams(int checks = 32, float eps = 0, bool sorted = true, int cores = 1 )
typedef enum {
False = 0,
True = 1,
Undefined
} tri_type;
struct SearchParams
{
SearchParams(int checks_ = 32, float eps_ = 0.0, bool sorted_ = true ) :
checks(checks_), eps(eps_), sorted(sorted_)
{
max_neighbors = -1;
use_heap = Undefined;
cores = 1;
matrices_in_gpu_ram = false;
}
// how many leafs to visit when searching for neighbours (-1 for unlimited)
(*this)["checks"] = checks;
int checks;
// search for eps-approximate neighbours (default: 0)
(*this)["eps"] = eps;
float eps;
// only for radius search, require neighbours sorted by distance (default: true)
(*this)["sorted"] = sorted;
bool sorted;
// maximum number of neighbors radius search should return (-1 for unlimited)
int max_neighbors;
// use a heap to manage the result set (default: Undefined)
tri_type use_heap;
// how many cores to assign to the search
// this parameter will be ignored if Intel TBB isn't available on the system or no "TBB" macro is defined
(*this)["cores"] = cores;
}
int cores;
// for GPU search indicates if matrices are already in GPU ram
bool matrices_in_gpu_ram;
};
......@@ -97,6 +115,13 @@ inline void print_params(const IndexParams& params)
}
}
inline void print_params(const SearchParams& params)
{
std::cout << "checks : " << params.checks << std::endl;
std::cout << "eps : " << params.eps << std::endl;
std::cout << "sorted : " << params.sorted << std::endl;
std::cout << "max_neighbors : " << params.max_neighbors << std::endl;
}
}
......
......@@ -200,7 +200,6 @@ private:
std::vector<DistIndex> dist_index_;
};
/**
* K-Nearest neighbour result set. Ensures that the elements inserted are unique
*/
......
......@@ -100,7 +100,9 @@ TEST_F(FlannTest, HandlesSingleCoreSearch)
int cores = 1;
start_timer("Searching KNN...");
index.knnSearch(query, indices, dists, GetNN(), flann::SearchParams(checks,eps,sorted,cores));
SearchParams params(checks,eps,sorted);
params.cores = cores;
index.knnSearch(query, indices, dists, GetNN(), params);
printf("done (%g seconds)\n", stop_timer());
float precision = compute_precision(match, indices);
......@@ -121,7 +123,9 @@ TEST_F(FlannTest, HandlesMultiCoreSearch)
int cores = 2;
start_timer("Searching KNN...");
index.knnSearch(query, indices, dists, GetNN(), flann::SearchParams(checks,eps,sorted,cores));
SearchParams params(checks,eps,sorted);
params.cores = cores;
index.knnSearch(query, indices, dists, GetNN(), params);
printf("done (%g seconds)\n", stop_timer());
float precision = compute_precision(match, indices);
......@@ -187,11 +191,14 @@ TEST_F(FlannCompareKnnTest, CompareMultiSingleCoreKnnSearchSorted)
int multi_core = -1;
start_timer("Searching KNN (single core)...");
int single_neighbor_count = index.knnSearch(query, indices_single, dists_single, GetNN(), flann::SearchParams(checks,eps,sorted,single_core));
SearchParams params(checks,eps,sorted);
params.cores = single_core;
int single_neighbor_count = index.knnSearch(query, indices_single, dists_single, GetNN(), params);
printf("done (%g seconds)\n", stop_timer());
start_timer("Searching KNN (multi core)...");
int multi_neighbor_count = index.knnSearch(query, indices_multi, dists_multi, GetNN(), flann::SearchParams(checks,eps,sorted,multi_core));
params.cores = multi_core;
int multi_neighbor_count = index.knnSearch(query, indices_multi, dists_multi, GetNN(), params);
printf("done (%g seconds)\n", stop_timer());
EXPECT_EQ(single_neighbor_count, multi_neighbor_count);
......@@ -215,11 +222,14 @@ TEST_F(FlannCompareKnnTest, CompareMultiSingleCoreKnnSearchUnsorted)
int multi_core = -1;
start_timer("Searching KNN (single core)...");
int single_neighbor_count = index.knnSearch(query, indices_single, dists_single, GetNN(), flann::SearchParams(checks,eps,sorted,single_core));
SearchParams params(checks,eps,sorted);
params.cores = single_core;
int single_neighbor_count = index.knnSearch(query, indices_single, dists_single, GetNN(), params);
printf("done (%g seconds)\n", stop_timer());
start_timer("Searching KNN (multi core)...");
int multi_neighbor_count = index.knnSearch(query, indices_multi, dists_multi, GetNN(), flann::SearchParams(checks,eps,sorted,multi_core));
params.cores = multi_core;
int multi_neighbor_count = index.knnSearch(query, indices_multi, dists_multi, GetNN(), params);
printf("done (%g seconds)\n", stop_timer());
EXPECT_EQ(single_neighbor_count, multi_neighbor_count);
......@@ -293,11 +303,14 @@ TEST_F(FlannCompareRadiusTest, CompareMultiSingleCoreRadiusSearchSorted)
int multi_core = -1;
start_timer("Searching Radius (single core)...");
int single_neighbor_count = index.radiusSearch(query, indices_single, dists_single, GetRadius(), flann::SearchParams(checks,eps,sorted,single_core));
SearchParams params(checks,eps,sorted);
params.cores = single_core;
int single_neighbor_count = index.radiusSearch(query, indices_single, dists_single, GetRadius(), params);
printf("done (%g seconds)\n", stop_timer());
start_timer("Searching Radius (multi core)...");
int multi_neighbor_count = index.radiusSearch(query, indices_multi, dists_multi, GetRadius(), flann::SearchParams(checks,eps,sorted,multi_core));
params.cores = multi_core;
int multi_neighbor_count = index.radiusSearch(query, indices_multi, dists_multi, GetRadius(), params);
printf("done (%g seconds)\n", stop_timer());
EXPECT_EQ(single_neighbor_count, multi_neighbor_count);
......@@ -321,11 +334,14 @@ TEST_F(FlannCompareRadiusTest, CompareMultiSingleCoreRadiusSearchUnsorted)
int multi_core = -1;
start_timer("Searching Radius (single core)...");
int single_neighbor_count = index.radiusSearch(query, indices_single, dists_single, GetRadius(), flann::SearchParams(checks,eps,sorted,single_core));
SearchParams params(checks,eps,sorted);
params.cores = single_core;
int single_neighbor_count = index.radiusSearch(query, indices_single, dists_single, GetRadius(), params);
printf("done (%g seconds)\n", stop_timer());
start_timer("Searching Radius (multi core)...");
int multi_neighbor_count = index.radiusSearch(query, indices_multi, dists_multi, GetRadius(), flann::SearchParams(checks,eps,sorted,multi_core));
params.cores = multi_core;
int multi_neighbor_count = index.radiusSearch(query, indices_multi, dists_multi, GetRadius(), params);
printf("done (%g seconds)\n", stop_timer());
EXPECT_EQ(single_neighbor_count, multi_neighbor_count);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册