From 123ca7e1c5547650f9501965b87c35d92127cf88 Mon Sep 17 00:00:00 2001 From: Takahiro Poly Horikawa Date: Thu, 27 Nov 2014 16:29:05 +0900 Subject: [PATCH 1/3] Parallize building kmeans index in flann --- .../include/opencv2/flann/kmeans_index.h | 85 +++++++++++++++---- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index bfc9b91453..1655ac6a11 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -69,7 +69,6 @@ struct KMeansIndexParams : public IndexParams } }; - /** * Hierarchical kmeans index * @@ -271,6 +270,68 @@ public: return FLANN_INDEX_KMEANS; } + class KMeansDistanceComputer : public cv::ParallelLoopBody + { + public: + KMeansDistanceComputer(Distance _distance, const Matrix& _dataset, + const int _branching, const int* _indices, const Matrix& _dcenters, const int _veclen, + int* _count, int* _belongs_to, std::vector& _radiuses, bool* _updated) + : distance(_distance) + , dataset(_dataset) + , branching(_branching) + , indices(_indices) + , dcenters(_dcenters) + , veclen(_veclen) + , count(_count) + , belongs_to(_belongs_to) + , radiuses(_radiuses) + , updated(_updated) + { + } + + void operator()(const cv::Range& range) const + { + const int begin = range.start; + const int end = range.end; + + for( int i = begin; inew_sq_dist) { + new_centroid = j; + sq_dist = new_sq_dist; + } + } + if (sq_dist > radiuses[new_centroid]) { + radiuses[new_centroid] = sq_dist; + } + if (new_centroid != belongs_to[i]) { + count[belongs_to[i]]--; + count[new_centroid]++; + belongs_to[i] = new_centroid; + updated[i] = true; + } else { + updated[i] = false; + } + } + } + + private: + Distance distance; + const Matrix& dataset; + const int branching; + const int* indices; + const Matrix& dcenters; + int veclen; + int* count; + int* belongs_to; + std::vector& radiuses; + bool* updated; + }; + /** * Index constructor * @@ -708,6 +769,7 @@ private: bool converged = false; int iteration = 0; + bool* updated = new bool[indices_length]; while (!converged && iterationnew_sq_dist) { - new_centroid = j; - sq_dist = new_sq_dist; - } - } - if (sq_dist>radiuses[new_centroid]) { - radiuses[new_centroid] = sq_dist; - } - if (new_centroid != belongs_to[i]) { - count[belongs_to[i]]--; - count[new_centroid]++; - belongs_to[i] = new_centroid; - + if (updated[i]) { converged = false; + break; } } @@ -828,6 +876,7 @@ private: delete[] centers; delete[] count; delete[] belongs_to; + delete[] updated; } From 180e54d09d13e90df722f5e0b821323d726f1380 Mon Sep 17 00:00:00 2001 From: Takahiro Poly Horikawa Date: Fri, 28 Nov 2014 18:39:49 +0900 Subject: [PATCH 2/3] - Use cv::Mutex to safely update converged flag - Use cv::AutoBuffer rather than new allocation - Fix "assignment operator could not be generated" warning --- .../include/opencv2/flann/kmeans_index.h | 48 ++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index 1655ac6a11..e0ee9618bc 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -69,6 +69,7 @@ struct KMeansIndexParams : public IndexParams } }; + /** * Hierarchical kmeans index * @@ -275,7 +276,7 @@ public: public: KMeansDistanceComputer(Distance _distance, const Matrix& _dataset, const int _branching, const int* _indices, const Matrix& _dcenters, const int _veclen, - int* _count, int* _belongs_to, std::vector& _radiuses, bool* _updated) + int* _count, int* _belongs_to, std::vector& _radiuses, bool& _converged, cv::Mutex& _mtx) : distance(_distance) , dataset(_dataset) , branching(_branching) @@ -285,7 +286,8 @@ public: , count(_count) , belongs_to(_belongs_to) , radiuses(_radiuses) - , updated(_updated) + , converged(_converged) + , mtx(_mtx) { } @@ -312,9 +314,9 @@ public: count[belongs_to[i]]--; count[new_centroid]++; belongs_to[i] = new_centroid; - updated[i] = true; - } else { - updated[i] = false; + mtx.lock(); + converged = false; + mtx.unlock(); } } } @@ -322,14 +324,15 @@ public: private: Distance distance; const Matrix& dataset; - const int branching; + int branching; const int* indices; const Matrix& dcenters; int veclen; int* count; int* belongs_to; std::vector& radiuses; - bool* updated; + bool& converged; + cv::Mutex& mtx; }; /** @@ -719,7 +722,8 @@ private: return; } - int* centers_idx = new int[branching]; + cv::AutoBuffer centers_idx_buf(branching); + int* centers_idx = (int*)centers_idx_buf; int centers_length; (this->*chooseCenters)(branching, indices, indices_length, centers_idx, centers_length); @@ -727,29 +731,30 @@ private: node->indices = indices; std::sort(node->indices,node->indices+indices_length); node->childs = NULL; - delete [] centers_idx; return; } - Matrix dcenters(new double[branching*veclen_],branching,veclen_); + cv::AutoBuffer dcenters_buf(branching*veclen_); + Matrix dcenters((double*)dcenters_buf,branching,veclen_); for (int i=0; i radiuses(branching); - int* count = new int[branching]; + cv::AutoBuffer count_buf(branching); + int* count = (int*)count_buf; for (int i=0; i belongs_to_buf(indices_length); + int* belongs_to = (int*)belongs_to_buf; for (int i=0; ichilds[c],indices+start, end-start, branching, level+1); start=end; } - - delete[] dcenters.data; - delete[] centers; - delete[] count; - delete[] belongs_to; - delete[] updated; } From 553bb7956e4d85fd8978d49913f3fb5b8a4cc566 Mon Sep 17 00:00:00 2001 From: Takahiro Poly Horikawa Date: Fri, 28 Nov 2014 19:33:52 +0900 Subject: [PATCH 3/3] Fix "assignment operator could not be generated" warnings --- modules/flann/include/opencv2/flann/kmeans_index.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index e0ee9618bc..b49b8ddded 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -275,7 +275,7 @@ public: { public: KMeansDistanceComputer(Distance _distance, const Matrix& _dataset, - const int _branching, const int* _indices, const Matrix& _dcenters, const int _veclen, + const int _branching, const int* _indices, const Matrix& _dcenters, const size_t _veclen, int* _count, int* _belongs_to, std::vector& _radiuses, bool& _converged, cv::Mutex& _mtx) : distance(_distance) , dataset(_dataset) @@ -324,15 +324,16 @@ public: private: Distance distance; const Matrix& dataset; - int branching; + const int branching; const int* indices; const Matrix& dcenters; - int veclen; + const size_t veclen; int* count; int* belongs_to; std::vector& radiuses; bool& converged; cv::Mutex& mtx; + KMeansDistanceComputer& operator=( const KMeansDistanceComputer & ) { return *this; } }; /**