* @brief Construct clusters in IVF * * @param data Data objects (N*DIM) * @param centroids Centroid vectors (K*DIM) * @param clustter_ids Cluster ID for each data objects */
| 168 | */ |
| 169 | inline void IVF::construct( |
| 170 | const float* data, const float* centroids, const PID* cluster_ids, bool faster = false, |
| 171 | size_t num_threads = std::numeric_limits<size_t>::max() |
| 172 | ) { |
| 173 | std::cout << "Start IVF construction...\n"; |
| 174 | |
| 175 | // get id list for each cluster |
| 176 | std::cout << "\tLoading clustering information...\n"; |
| 177 | std::vector<size_t> counts(num_cluster_, 0); |
| 178 | std::vector<std::vector<PID>> id_lists(num_cluster_); |
| 179 | for (size_t i = 0; i < num_; ++i) { |
| 180 | PID cid = cluster_ids[i]; |
| 181 | if (cid > num_cluster_) { |
| 182 | std::cerr << "Bad cluster id\n"; |
| 183 | exit(1); |
| 184 | } |
| 185 | id_lists[cid].push_back(static_cast<PID>(i)); |
| 186 | counts[cid] += 1; |
| 187 | } |
| 188 | |
| 189 | allocate_memory(counts); |
| 190 | |
| 191 | // init the cluster list |
| 192 | init_clusters(counts); |
| 193 | |
| 194 | // all rotated centroids |
| 195 | std::vector<float> rotated_centroids(num_cluster_ * padded_dim_); |
| 196 | |
| 197 | quant::RabitqConfig config; |
| 198 | if (faster) { |
| 199 | config = quant::faster_config(padded_dim_, ex_bits_ + 1); |
| 200 | } |
| 201 | |
| 202 | num_threads = std::min(num_threads, rabitqlib::total_threads()); |
| 203 | /* Quantize each cluster */ |
| 204 | #pragma omp parallel for schedule(dynamic) num_threads(num_threads) |
| 205 | for (size_t i = 0; i < num_cluster_; ++i) { |
| 206 | const float* cur_centroid = centroids + (i * dim_); |
| 207 | float* cur_rotated_c = &rotated_centroids[i * padded_dim_]; |
| 208 | Cluster& cp = cluster_lst_[i]; |
| 209 | quantize_cluster(cp, id_lists[i], data, cur_centroid, cur_rotated_c, config); |
| 210 | } |
| 211 | |
| 212 | this->initer_->add_vectors(rotated_centroids.data(), num_threads); |
| 213 | } |
| 214 | |
| 215 | inline void IVF::allocate_memory(const std::vector<size_t>& cluster_sizes) { |
| 216 | std::cout << "Allocating memory for IVF...\n"; |
| 217 | if (num_cluster_ < 20000UL) { |
no test coverage detected