| 191 | } |
| 192 | |
| 193 | DatasetPtr |
| 194 | BruteForce::SearchWithRequest(const SearchRequest& request) const { |
| 195 | std::shared_lock read_lock(this->global_mutex_); |
| 196 | |
| 197 | auto computer = this->inner_codes_->FactoryComputer(request.query_->GetFloat32Vectors()); |
| 198 | DistHeapPtr heap = nullptr; |
| 199 | ExecutorPtr executor = nullptr; |
| 200 | Filter* attr_filter = nullptr; |
| 201 | Filter* filter = nullptr; |
| 202 | if (request.filter_ != nullptr) { |
| 203 | filter = request.filter_.get(); |
| 204 | } |
| 205 | if (request.enable_attribute_filter_) { |
| 206 | auto& schema = this->attr_filter_index_->field_type_map_; |
| 207 | auto expr = AstParse(request.attribute_filter_str_, &schema); |
| 208 | executor = Executor::MakeInstance(this->allocator_, expr, this->attr_filter_index_); |
| 209 | executor->Init(); |
| 210 | executor->Clear(); |
| 211 | attr_filter = executor->Run(); |
| 212 | } |
| 213 | |
| 214 | std::atomic<uint32_t> dist_cmp{0}; |
| 215 | |
| 216 | auto brute_force_params = BruteForceSearchParameters::FromJson(request.params_str_); |
| 217 | auto parallel_count = brute_force_params.parallel_search_thread_count; |
| 218 | std::vector<DistHeapPtr> heaps(parallel_count); |
| 219 | for (auto& cur_heap : heaps) { |
| 220 | cur_heap = DistanceHeap::MakeInstanceBySize<true, true>(this->allocator_, request.topk_); |
| 221 | } |
| 222 | auto search_func = [&](InnerIdType start, InnerIdType end, const DistHeapPtr& cur_heap) { |
| 223 | float cur_min_dist = std::numeric_limits<float>::max(); |
| 224 | uint32_t dist_cmp_local = 0; |
| 225 | for (InnerIdType i = start; i < end; ++i) { |
| 226 | float dist = 0.0F; |
| 227 | if (attr_filter != nullptr and not attr_filter->CheckValid(i)) { |
| 228 | continue; |
| 229 | } |
| 230 | if (filter == nullptr or filter->CheckValid(this->label_table_->GetLabelById(i))) { |
| 231 | inner_codes_->Query(&dist, computer, &i, 1); |
| 232 | ++dist_cmp_local; |
| 233 | cur_heap->Push(dist, i); |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | dist_cmp.fetch_add(dist_cmp_local, std::memory_order_relaxed); |
| 238 | }; |
| 239 | |
| 240 | if (parallel_count == 1 || this->thread_pool_ == nullptr) { |
| 241 | search_func(0, total_count_, heaps[0]); |
| 242 | heap = heaps[0]; |
| 243 | } else { |
| 244 | std::vector<std::future<void>> futures; |
| 245 | auto chunk_size = (total_count_ + parallel_count - 1) / parallel_count; |
| 246 | for (auto i = 0; i < parallel_count; ++i) { |
| 247 | auto start = i * chunk_size; |
| 248 | auto end = std::min(start + chunk_size, total_count_); |
| 249 | auto future = this->thread_pool_->GeneralEnqueue(search_func, start, end, heaps[i]); |
| 250 | futures.emplace_back(std::move(future)); |
no test coverage detected