| 483 | |
| 484 | template<typename TIndex, class HashMap> |
| 485 | void MultiMapCompute(OpKernelContext* context, const Tensor& input, |
| 486 | Tensor* idx, int64 axis, int64* uniq_size_out, |
| 487 | int32 num_buckets, int64 unique_ratio_hint, int num_sparse, |
| 488 | google::dense_hash_map<int, TIndex>* counter_map, Tensor* output) { |
| 489 | auto Tin = input.vec<int64>(); |
| 490 | const int64 N = input.NumElements(); |
| 491 | |
| 492 | auto idx_vec = idx->template vec<TIndex>(); |
| 493 | |
| 494 | auto thread_pool = |
| 495 | context->device()->tensorflow_cpu_worker_threads()->workers; |
| 496 | |
| 497 | // Parallel Step 0: Partition. |
| 498 | int32 num_partitions = num_buckets; |
| 499 | std::unique_ptr<int64[]> partitions{new int64[num_partitions * num_buckets]}; |
| 500 | |
| 501 | static IdHash hasher; |
| 502 | Partitioner map_parter(N, num_partitions); |
| 503 | auto PartitionTask = [N, num_buckets, &Tin, &partitions, &map_parter, &idx_vec] |
| 504 | (int32 task_id, int32 num_tasks) { |
| 505 | auto st = Status::OK(); |
| 506 | int64* partition = partitions.get() + task_id * num_buckets; |
| 507 | for (int64 i = 0; i < num_buckets; ++i) { |
| 508 | partition[i] = -1; |
| 509 | } |
| 510 | const Range* range = map_parter.GetRange(task_id); |
| 511 | |
| 512 | for (int64 i = range->Start(); i < range->End(); ++i) { |
| 513 | auto& id = Tin(i); |
| 514 | if (unlikely(id == kPreseverdEmptyKey)) { |
| 515 | st = errors::InvalidArgument( |
| 516 | "Input id is preserved key of dense_hash_map, " |
| 517 | "not supported: ", id); |
| 518 | break; |
| 519 | } |
| 520 | int64 bucket = (hasher(id) >> 54) % num_buckets; |
| 521 | idx_vec(i) = partition[bucket]; |
| 522 | partition[bucket] = i; |
| 523 | } |
| 524 | return st; |
| 525 | }; |
| 526 | |
| 527 | SummaryTaskRunner<Status, StatusSummaryUpdater> t0_runner( |
| 528 | PartitionTask, Status::OK(), thread_pool, num_partitions); |
| 529 | t0_runner.Run(); |
| 530 | OP_REQUIRES_OK(context, t0_runner.summary()); |
| 531 | |
| 532 | // Parallel Step 1: Build hash maps. |
| 533 | HashMap uniq_maps_ptr[num_buckets]; |
| 534 | HashMap* uniq_maps = uniq_maps_ptr; |
| 535 | auto MapBuildTask = [N, num_partitions, &Tin, &partitions, |
| 536 | uniq_maps, &idx_vec, unique_ratio_hint] (int32 task_id, int32 num_tasks) { |
| 537 | auto& uniq = uniq_maps[task_id]; |
| 538 | HashMapInitializer<HashMap>::Reserve(&uniq, N / num_tasks / unique_ratio_hint); |
| 539 | |
| 540 | for (int64 k = 0; k < num_partitions; ++k) { |
| 541 | int64* partition = partitions.get() + k * num_tasks + task_id; |
| 542 | int64 next_idx = *partition; |
nothing calls this directly
no test coverage detected