Find method is the continuation of processing from early_filter. Its input consists of hash values and the output of early_filter. It updates match bit-vector, clearing it from any false positives that might have been left by early_filter. It also outputs group ids, which are needed to be able to execute key comparisons. The caller may discard group ids if only the match flag is of interest.
| 434 | // match flag is of interest. |
| 435 | // |
| 436 | void SwissTable::find(const int num_keys, const uint32_t* hashes, |
| 437 | uint8_t* inout_match_bitvector, const uint8_t* local_slots, |
| 438 | uint32_t* out_group_ids, util::TempVectorStack* temp_stack, |
| 439 | const EqualImpl& equal_impl, void* callback_ctx) const { |
| 440 | // Temporary selection vector. |
| 441 | // It will hold ids of keys for which we do not know yet |
| 442 | // if they have a match in hash table or not. |
| 443 | // |
| 444 | // Initially the set of these keys is represented by input |
| 445 | // match bit-vector. Eventually we switch from this bit-vector |
| 446 | // to array of ids. |
| 447 | // |
| 448 | ARROW_DCHECK(num_keys <= (1 << log_minibatch_)); |
| 449 | auto ids_buf = util::TempVectorHolder<uint16_t>(temp_stack, num_keys); |
| 450 | uint16_t* ids = ids_buf.mutable_data(); |
| 451 | int num_ids; |
| 452 | |
| 453 | int64_t num_matches = arrow::internal::CountSetBits(inout_match_bitvector, |
| 454 | /*offset=*/0, num_keys); |
| 455 | |
| 456 | // If there is a high density of selected input rows |
| 457 | // (majority of them are present in the selection), |
| 458 | // we may run some computation on all of the input rows ignoring |
| 459 | // selection and then filter the output of this computation |
| 460 | // (pre-filtering vs post-filtering). |
| 461 | // |
| 462 | bool visit_all = num_matches > 0 && num_matches > 3 * num_keys / 4; |
| 463 | if (visit_all) { |
| 464 | extract_group_ids(num_keys, nullptr, hashes, local_slots, out_group_ids); |
| 465 | run_comparisons(num_keys, nullptr, inout_match_bitvector, out_group_ids, &num_ids, |
| 466 | ids, equal_impl, callback_ctx); |
| 467 | } else { |
| 468 | util::bit_util::bits_to_indexes(1, hardware_flags_, num_keys, inout_match_bitvector, |
| 469 | &num_ids, ids); |
| 470 | extract_group_ids(num_ids, ids, hashes, local_slots, out_group_ids); |
| 471 | run_comparisons(num_ids, ids, nullptr, out_group_ids, &num_ids, ids, equal_impl, |
| 472 | callback_ctx); |
| 473 | } |
| 474 | |
| 475 | if (num_ids == 0) { |
| 476 | return; |
| 477 | } |
| 478 | |
| 479 | auto slot_ids_buf = util::TempVectorHolder<uint32_t>(temp_stack, num_keys); |
| 480 | uint32_t* slot_ids = slot_ids_buf.mutable_data(); |
| 481 | init_slot_ids(num_ids, ids, hashes, local_slots, inout_match_bitvector, slot_ids); |
| 482 | |
| 483 | while (num_ids > 0) { |
| 484 | int num_ids_last_iteration = num_ids; |
| 485 | num_ids = 0; |
| 486 | for (int i = 0; i < num_ids_last_iteration; ++i) { |
| 487 | int id = ids[i]; |
| 488 | uint32_t next_slot_id; |
| 489 | bool match_found = find_next_stamp_match(hashes[id], slot_ids[id], &next_slot_id, |
| 490 | &(out_group_ids[id])); |
| 491 | slot_ids[id] = next_slot_id; |
| 492 | // If next match was not found then clear match bit in a bit vector |
| 493 | if (!match_found) { |