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

Method CreateCollocatedAndScanInstances

be/src/scheduling/scheduler.cc:795–970  ·  view source on GitHub ↗

Maybe the easiest way to understand the objective of this algorithm is as a generalization of two simpler instance creation algorithms that decide how many instances of a fragment to create on each node, given a set of nodes that were already chosen by previous scheduling steps: 1. Instance creation for an interior fragment (i.e. a fragment without scans) without a UNION, where we create one finst

Source from the content-addressed store, hash-verified

793// b) Create the finstances, based on the computed parallelism and assign the scan
794// ranges to it.
795void Scheduler::CreateCollocatedAndScanInstances(const ExecutorConfig& executor_config,
796 FragmentScheduleState* fragment_state, ScheduleState* state) {
797 const TPlanFragment& fragment = fragment_state->fragment;
798 bool has_union = ContainsUnionNode(fragment.plan);
799 DCHECK(has_union || ContainsScanNode(fragment.plan));
800 // Build a map of hosts to the num instances this fragment should have, before we take
801 // into account scan ranges. If this fragment has input fragments, we always run with
802 // at least the same num instances as the input fragment.
803 std::unordered_map<NetworkAddressPB, int> instances_per_host;
804
805 // Add hosts of input fragments, counting the number of instances of the fragment.
806 // Only do this if there's a union - otherwise only consider the parallelism of
807 // the input scan, for consistency with the previous behaviour of only using
808 // the parallelism of the scan.
809 if (has_union) {
810 for (FragmentIdx idx : fragment_state->exchange_input_fragments) {
811 std::unordered_map<NetworkAddressPB, int> input_fragment_instances_per_host;
812 const FragmentScheduleState& input_state = *state->GetFragmentScheduleState(idx);
813 for (const FInstanceScheduleState& instance_state : input_state.instance_states) {
814 ++input_fragment_instances_per_host[instance_state.host];
815 }
816 // Merge with the existing hosts by taking the max num instances.
817 if (instances_per_host.empty()) {
818 // Optimization for the common case of one input fragment.
819 instances_per_host = move(input_fragment_instances_per_host);
820 } else {
821 for (auto& entry : input_fragment_instances_per_host) {
822 int& num_instances = instances_per_host[entry.first];
823 num_instances = max(num_instances, entry.second);
824 }
825 }
826 }
827 }
828
829 // Add hosts of scan nodes.
830 vector<TPlanNodeId> scan_node_ids = FindScanNodes(fragment.plan);
831 DCHECK(has_union || scan_node_ids.size() == 1) << "This method may need revisiting "
832 << "for plans with no union and multiple scans per fragment";
833 vector<NetworkAddressPB> scan_hosts;
834 GetScanHosts(scan_node_ids, *fragment_state, &scan_hosts);
835 if (scan_hosts.empty() && instances_per_host.empty()) {
836 // None of the scan nodes have any scan ranges and there is no input fragment feeding
837 // into this fragment; run it on a random executor.
838 // TODO TODO: the TODO below seems partially stale
839 // TODO: we'll need to revisit this strategy once we can partition joins
840 // (in which case this fragment might be executing a right outer join
841 // with a large build table)
842 vector<BackendDescriptorPB> all_executors =
843 executor_config.group.GetAllExecutorDescriptors();
844 int idx = std::uniform_int_distribution<int>(0, all_executors.size() - 1)(
845 *state->rng());
846 const BackendDescriptorPB& be_desc = all_executors[idx];
847 scan_hosts.push_back(be_desc.address());
848 }
849 for (const NetworkAddressPB& host_addr : scan_hosts) {
850 // Ensure that the num instances is at least as many as input fragments. We don't
851 // want to increment if there were already some instances from the input fragment,
852 // since that could result in too high a num_instances.

Callers

nothing calls this directly

Calls 15

moveFunction · 0.85
maxFunction · 0.85
rngMethod · 0.80
push_backMethod · 0.80
GetNodeMethod · 0.80
clearMethod · 0.65
emptyMethod · 0.45
sizeMethod · 0.45
requestMethod · 0.45
beginMethod · 0.45

Tested by

no test coverage detected