- Use cv::Mutex to safely update converged flag

- Use cv::AutoBuffer rather than new allocation
- Fix "assignment operator could not be generated" warning
parent 123ca7e1
...@@ -69,6 +69,7 @@ struct KMeansIndexParams : public IndexParams ...@@ -69,6 +69,7 @@ struct KMeansIndexParams : public IndexParams
} }
}; };
/** /**
* Hierarchical kmeans index * Hierarchical kmeans index
* *
...@@ -275,7 +276,7 @@ public: ...@@ -275,7 +276,7 @@ public:
public: public:
KMeansDistanceComputer(Distance _distance, const Matrix<ElementType>& _dataset, KMeansDistanceComputer(Distance _distance, const Matrix<ElementType>& _dataset,
const int _branching, const int* _indices, const Matrix<double>& _dcenters, const int _veclen, const int _branching, const int* _indices, const Matrix<double>& _dcenters, const int _veclen,
int* _count, int* _belongs_to, std::vector<DistanceType>& _radiuses, bool* _updated) int* _count, int* _belongs_to, std::vector<DistanceType>& _radiuses, bool& _converged, cv::Mutex& _mtx)
: distance(_distance) : distance(_distance)
, dataset(_dataset) , dataset(_dataset)
, branching(_branching) , branching(_branching)
...@@ -285,7 +286,8 @@ public: ...@@ -285,7 +286,8 @@ public:
, count(_count) , count(_count)
, belongs_to(_belongs_to) , belongs_to(_belongs_to)
, radiuses(_radiuses) , radiuses(_radiuses)
, updated(_updated) , converged(_converged)
, mtx(_mtx)
{ {
} }
...@@ -312,9 +314,9 @@ public: ...@@ -312,9 +314,9 @@ public:
count[belongs_to[i]]--; count[belongs_to[i]]--;
count[new_centroid]++; count[new_centroid]++;
belongs_to[i] = new_centroid; belongs_to[i] = new_centroid;
updated[i] = true; mtx.lock();
} else { converged = false;
updated[i] = false; mtx.unlock();
} }
} }
} }
...@@ -322,14 +324,15 @@ public: ...@@ -322,14 +324,15 @@ public:
private: private:
Distance distance; Distance distance;
const Matrix<ElementType>& dataset; const Matrix<ElementType>& dataset;
const int branching; int branching;
const int* indices; const int* indices;
const Matrix<double>& dcenters; const Matrix<double>& dcenters;
int veclen; int veclen;
int* count; int* count;
int* belongs_to; int* belongs_to;
std::vector<DistanceType>& radiuses; std::vector<DistanceType>& radiuses;
bool* updated; bool& converged;
cv::Mutex& mtx;
}; };
/** /**
...@@ -719,7 +722,8 @@ private: ...@@ -719,7 +722,8 @@ private:
return; return;
} }
int* centers_idx = new int[branching]; cv::AutoBuffer<int> centers_idx_buf(branching);
int* centers_idx = (int*)centers_idx_buf;
int centers_length; int centers_length;
(this->*chooseCenters)(branching, indices, indices_length, centers_idx, centers_length); (this->*chooseCenters)(branching, indices, indices_length, centers_idx, centers_length);
...@@ -727,29 +731,30 @@ private: ...@@ -727,29 +731,30 @@ private:
node->indices = indices; node->indices = indices;
std::sort(node->indices,node->indices+indices_length); std::sort(node->indices,node->indices+indices_length);
node->childs = NULL; node->childs = NULL;
delete [] centers_idx;
return; return;
} }
Matrix<double> dcenters(new double[branching*veclen_],branching,veclen_); cv::AutoBuffer<double> dcenters_buf(branching*veclen_);
Matrix<double> dcenters((double*)dcenters_buf,branching,veclen_);
for (int i=0; i<centers_length; ++i) { for (int i=0; i<centers_length; ++i) {
ElementType* vec = dataset_[centers_idx[i]]; ElementType* vec = dataset_[centers_idx[i]];
for (size_t k=0; k<veclen_; ++k) { for (size_t k=0; k<veclen_; ++k) {
dcenters[i][k] = double(vec[k]); dcenters[i][k] = double(vec[k]);
} }
} }
delete[] centers_idx;
std::vector<DistanceType> radiuses(branching); std::vector<DistanceType> radiuses(branching);
int* count = new int[branching]; cv::AutoBuffer<int> count_buf(branching);
int* count = (int*)count_buf;
for (int i=0; i<branching; ++i) { for (int i=0; i<branching; ++i) {
radiuses[i] = 0; radiuses[i] = 0;
count[i] = 0; count[i] = 0;
} }
// assign points to clusters // assign points to clusters
int* belongs_to = new int[indices_length]; cv::AutoBuffer<int> belongs_to_buf(indices_length);
int* belongs_to = (int*)belongs_to_buf;
for (int i=0; i<indices_length; ++i) { for (int i=0; i<indices_length; ++i) {
DistanceType sq_dist = distance_(dataset_[indices[i]], dcenters[0], veclen_); DistanceType sq_dist = distance_(dataset_[indices[i]], dcenters[0], veclen_);
...@@ -769,7 +774,6 @@ private: ...@@ -769,7 +774,6 @@ private:
bool converged = false; bool converged = false;
int iteration = 0; int iteration = 0;
bool* updated = new bool[indices_length];
while (!converged && iteration<iterations_) { while (!converged && iteration<iterations_) {
converged = true; converged = true;
iteration++; iteration++;
...@@ -794,13 +798,9 @@ private: ...@@ -794,13 +798,9 @@ private:
} }
// reassign points to clusters // reassign points to clusters
parallel_for_(cv::Range(0, indices_length), KMeansDistanceComputer(distance_, dataset_, branching, indices, dcenters, veclen_, count, belongs_to, radiuses, updated)); cv::Mutex mtx;
for (int i=0; i<indices_length; ++i) { KMeansDistanceComputer invoker(distance_, dataset_, branching, indices, dcenters, veclen_, count, belongs_to, radiuses, converged, mtx);
if (updated[i]) { parallel_for_(cv::Range(0, (int)indices_length), invoker);
converged = false;
break;
}
}
for (int i=0; i<branching; ++i) { for (int i=0; i<branching; ++i) {
// if one cluster converges to an empty cluster, // if one cluster converges to an empty cluster,
...@@ -871,12 +871,6 @@ private: ...@@ -871,12 +871,6 @@ private:
computeClustering(node->childs[c],indices+start, end-start, branching, level+1); computeClustering(node->childs[c],indices+start, end-start, branching, level+1);
start=end; start=end;
} }
delete[] dcenters.data;
delete[] centers;
delete[] count;
delete[] belongs_to;
delete[] updated;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment