MCPcopy Create free account
hub / github.com/apache/impala / GetRemoteExecutorCandidates

Method GetRemoteExecutorCandidates

be/src/scheduling/scheduler.cc:1643–1702  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1641}
1642
1643void Scheduler::AssignmentCtx::GetRemoteExecutorCandidates(
1644 const THdfsFileSplit* hdfs_file_split, int num_candidates,
1645 vector<IpAddr>* remote_executor_candidates) {
1646 // This should be given an empty vector
1647 DCHECK_EQ(remote_executor_candidates->size(), 0);
1648 // This function should not be called with 'num_candidates' exceeding the number of
1649 // executors.
1650 DCHECK_LE(num_candidates, executor_group_.NumExecutors());
1651 // Two different hashes of the filename can result in the same executor.
1652 // The function should return distinct executors, so it may need to do more hashes
1653 // than 'num_candidates'.
1654 unordered_set<IpAddr> distinct_backends;
1655 distinct_backends.reserve(num_candidates);
1656 // Generate multiple hashes of the file split by using the hash as a seed to a PRNG.
1657 // Note: The hash includes the partition path hash, the filename (relative to the
1658 // partition directory), and the offset. The offset is used to allow very large files
1659 // that have multiple splits to be spread across more executors.
1660 uint32_t hash = static_cast<uint32_t>(hdfs_file_split->partition_path_hash);
1661 hash = HashUtil::Hash(hdfs_file_split->relative_path.data(),
1662 hdfs_file_split->relative_path.length(), hash);
1663 hash = HashUtil::Hash(&hdfs_file_split->offset, sizeof(hdfs_file_split->offset), hash);
1664 pcg32 prng(hash);
1665 // The function should return distinct executors, so it may need to do more hashes
1666 // than 'num_candidates'. To avoid any problem scenarios, limit the total number of
1667 // iterations. The number of iterations is set to a reasonably high level, because
1668 // on average the loop short circuits considerably earlier. Using a higher number of
1669 // iterations is useful for smaller clusters where we are using this function to get
1670 // all the backends in a consistent order rather than picking a consistent subset.
1671 // Suppose there are three nodes and the number of remote executor candidates is three.
1672 // One can calculate the probability of picking three distinct executors in at most
1673 // n iterations. For n=3, the second pick must not overlap the first (probability 2/3),
1674 // and the third pick must not be either the first or second (probability 1/3). So:
1675 // P(3) = 1*(2/3)*(1/3)=2/9
1676 // The probability that it is done in at most n+1 steps is the probability that
1677 // it completed in n steps combined with the probability that it completes in the n+1st
1678 // step. In order to complete in the n+1st step, the previous n steps must not have
1679 // all landed on a single backend (probability (1/3)^(n-1)) and this step must not land
1680 // on the two backends already chosen (probability 1/3). So, the recursive step is:
1681 // P(n+1) = P(n) + (1 - P(n))*(1-(1/3)^(n-1))*(1/3)
1682 // Here are some example probabilities:
1683 // Probability of completing in at most 5 iterations: 0.6284
1684 // Probability of completing in at most 10 iterations: 0.9506
1685 // Probability of completing in at most 15 iterations: 0.9935
1686 // Probability of completing in at most 20 iterations: 0.9991
1687 int max_iterations = num_candidates * MAX_ITERATIONS_PER_EXECUTOR_CANDIDATE;
1688 for (int i = 0; i < max_iterations; ++i) {
1689 // Look up nearest IpAddr
1690 const IpAddr* executor_addr = executor_group_.GetHashRing()->GetNode(prng());
1691 DCHECK(executor_addr != nullptr);
1692 auto insert_ret = distinct_backends.insert(*executor_addr);
1693 // The return type of unordered_set.insert() is a pair<iterator, bool> where the
1694 // second element is whether this was a new element. If this is a new element,
1695 // add this element to the return vector.
1696 if (insert_ret.second) {
1697 remote_executor_candidates->push_back(*executor_addr);
1698 }
1699 // Short-circuit if we reach the appropriate number of replicas
1700 if (remote_executor_candidates->size() == num_candidates) break;

Callers 1

Calls 10

HashFunction · 0.85
NumExecutorsMethod · 0.80
reserveMethod · 0.80
GetNodeMethod · 0.80
GetHashRingMethod · 0.80
push_backMethod · 0.80
sizeMethod · 0.45
dataMethod · 0.45
lengthMethod · 0.45
insertMethod · 0.45

Tested by

no test coverage detected