VWDictionary: use multi-core FLANN kNN search (#1760)

* VWDictionary: use multi-core FLANN kNN search

* Add parameter with default 1 thread

* Kp/FlannTreads plumbing  to UI. Also added to performance tests for comparison.

* fixing ci error

* dump debug data for windows ci

* Adding  more dll debugging report windows ci

* install vc2012 runtime explicitly

* updated comment

---------

Co-authored-by: matlabbe <[email protected]>
This commit is contained in:
Torjus Iveland
2026-09-10 23:22:00 -07:00
committed by GitHub
co-authored by matlabbe
parent fb457255b7
commit 2fbbe19d70
10 changed files with 283 additions and 32 deletions
+31 -3
View File
@@ -36,9 +36,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtflann/flann.hpp"
#include "nanoflann/NanoFlannIndex.h"
#include <boost/crc.hpp>
#ifdef _OPENMP
#include <omp.h>
#endif
namespace rtabmap {
namespace {
// A count of 0 means one thread per core, as Kp/FlannThreads spells it.
// rtflann would reach the same place by leaving num_threads(0) to OpenMP, but
// only where it is compiled with it: resolving the count here makes 0 mean the
// same thing in both builds, and keeps a negative count from reaching
// num_threads(), where it wraps around to an unsigned and asks the runtime for
// billions of threads.
int resolveCores(int cores)
{
if(cores > 0)
{
return cores;
}
#ifdef _OPENMP
return omp_get_max_threads();
#else
return 1;
#endif
}
}
FlannIndex::FlannIndex():
index_(0),
nanoIndex_(0),
@@ -910,7 +934,8 @@ void FlannIndex::knnSearch(
int knn,
int checks,
float eps,
bool sorted) const
bool sorted,
int cores) const
{
if(nanoIndex_)
{
@@ -930,6 +955,7 @@ void FlannIndex::knnSearch(
rtflann::Matrix<size_t> indicesF((size_t*)indicesBuffer.data(), query.rows, knn);
rtflann::SearchParams params = rtflann::SearchParams(checks, eps, sorted);
params.cores = resolveCores(cores);
if(featuresType_ == CV_8UC1)
{
@@ -974,11 +1000,12 @@ void FlannIndex::radiusSearch(
int maxNeighbors,
int checks,
float eps,
bool sorted) const
bool sorted,
int cores) const
{
if(nanoIndex_)
{
// "checks" doesn't apply
// "checks" and "cores" don't apply, it searches on one core
nanoIndex_->radiusSearch(query, indices, dists, radius, maxNeighbors, eps, sorted);
return;
}
@@ -990,6 +1017,7 @@ void FlannIndex::radiusSearch(
rtflann::SearchParams params = rtflann::SearchParams(checks, eps, sorted);
params.max_neighbors = maxNeighbors<=0?-1:maxNeighbors; // -1 is all in radius
params.cores = resolveCores(cores);
if(featuresType_ == CV_8UC1)
{
+4 -2
View File
@@ -101,6 +101,7 @@ VWDictionary::VWDictionary(const ParametersMap & parameters) :
_incrementalDictionary(Parameters::defaultKpIncrementalDictionary()),
_incrementalFlann(Parameters::defaultKpIncrementalFlann()),
_rebalancingFactor(Parameters::defaultKpFlannRebalancingFactor()),
_flannThreads(Parameters::defaultKpFlannThreads()),
_byteToFloat(Parameters::defaultKpByteToFloat()),
_nndrRatio(Parameters::defaultKpNndrRatio()),
_newDictionaryPath(Parameters::defaultKpDictionaryPath()),
@@ -130,6 +131,7 @@ void VWDictionary::parseParameters(const ParametersMap & parameters)
Parameters::parse(parameters, Parameters::kKpSerializeWithChecksum(), _serializeWithChecksum);
Parameters::parse(parameters, Parameters::kKpIncrementalFlann(), _incrementalFlann);
Parameters::parse(parameters, Parameters::kKpFlannRebalancingFactor(), _rebalancingFactor);
Parameters::parse(parameters, Parameters::kKpFlannThreads(), _flannThreads);
bool byteToFloat = _byteToFloat;
Parameters::parse(parameters, Parameters::kKpByteToFloat(), _byteToFloat);
@@ -1074,7 +1076,7 @@ std::list<int> VWDictionary::addNewWords(
if(isFlannStrategy(_strategy))
{
_flannIndex->knnSearch(descriptors, results, dists, k, KNN_CHECKS);
_flannIndex->knnSearch(descriptors, results, dists, k, KNN_CHECKS, 0.0f, true, _flannThreads);
}
else if(_strategy == kNNBruteForce)
{
@@ -1396,7 +1398,7 @@ std::vector<int> VWDictionary::findNN(const cv::Mat & queryIn) const
if(isFlannStrategy(_strategy))
{
_flannIndex->knnSearch(query, results, dists, k, KNN_CHECKS);
_flannIndex->knnSearch(query, results, dists, k, KNN_CHECKS, 0.0f, true, _flannThreads);
}
else if(_strategy == kNNBruteForce)
{