Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 3.9k
[PipelineX](improvement) Prepare tasks in parallel#40270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -116,9 +116,13 @@ PipelineXFragmentContext::~PipelineXFragmentContext() { | ||
| auto st = _query_ctx->exec_status(); | ||
| _tasks.clear(); | ||
| if (!_task_runtime_states.empty()) { | ||
| for (auto& runtime_state : _task_runtime_states) { | ||
| _call_back(runtime_state.get(), &st); | ||
| runtime_state.reset(); | ||
| for (auto& runtime_states : _task_runtime_states) { | ||
| for (auto& runtime_state : runtime_states) { | ||
| if (runtime_state) { | ||
| _call_back(runtime_state.get(), &st); | ||
| runtime_state.reset(); | ||
| } | ||
| } | ||
| } | ||
| } else { | ||
| _call_back(nullptr, &st); | ||
| @@ -182,7 +186,8 @@ void PipelineXFragmentContext::cancel(const PPlanFragmentCancelReason& reason, | ||
| } | ||
| } | ||
| Status PipelineXFragmentContext::prepare(const doris::TPipelineFragmentParams& request) { | ||
| Status PipelineXFragmentContext::prepare(const doris::TPipelineFragmentParams& request, | ||
yiguolei marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ThreadPool* thread_pool) { | ||
| if (_prepared) { | ||
| return Status::InternalError("Already prepared"); | ||
| } | ||
| @@ -210,7 +215,6 @@ Status PipelineXFragmentContext::prepare(const doris::TPipelineFragmentParams& r | ||
| _runtime_state = RuntimeState::create_unique(request.query_id, request.fragment_id, | ||
| request.query_options, _query_ctx->query_globals, | ||
| _exec_env, _query_ctx.get()); | ||
| SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(_runtime_state->query_mem_tracker()); | ||
| if (request.__isset.backend_id) { | ||
| _runtime_state->set_backend_id(request.backend_id); | ||
| @@ -284,7 +288,7 @@ Status PipelineXFragmentContext::prepare(const doris::TPipelineFragmentParams& r | ||
| } | ||
| // 5. Build pipeline tasks and initialize local state. | ||
| RETURN_IF_ERROR(_build_pipeline_tasks(request)); | ||
| RETURN_IF_ERROR(_build_pipeline_x_tasks(request, thread_pool)); | ||
| _init_next_report_time(); | ||
| @@ -511,11 +515,17 @@ Status PipelineXFragmentContext::_create_data_sink(ObjectPool* pool, const TData | ||
| return Status::OK(); | ||
| } | ||
| Status PipelineXFragmentContext::_build_pipeline_tasks( | ||
| const doris::TPipelineFragmentParams& request) { | ||
| Status PipelineXFragmentContext::_build_pipeline_x_tasks( | ||
yiguolei marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. yiguolei marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. yiguolei marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. yiguolei marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| const doris::TPipelineFragmentParams& request, ThreadPool* thread_pool) { | ||
| _total_tasks = 0; | ||
| int target_size = request.local_params.size(); | ||
| _tasks.resize(target_size); | ||
| _fragment_instance_ids.resize(target_size); | ||
| _runtime_filter_states.resize(target_size); | ||
| _task_runtime_states.resize(_pipelines.size()); | ||
| for (size_t pip_idx = 0; pip_idx < _pipelines.size(); pip_idx++) { | ||
| _task_runtime_states[pip_idx].resize(_pipelines[pip_idx]->num_tasks()); | ||
| } | ||
| auto& pipeline_id_to_profile = _runtime_state->pipeline_id_to_profile(); | ||
| DCHECK(pipeline_id_to_profile.empty()); | ||
| pipeline_id_to_profile.resize(_pipelines.size()); | ||
| @@ -528,10 +538,10 @@ Status PipelineXFragmentContext::_build_pipeline_tasks( | ||
| } | ||
| } | ||
| for (size_t i = 0; i < target_size; i++) { | ||
| auto pre_and_submit = [&](int i, PipelineFragmentContext* ctx) { | ||
| const auto& local_params = request.local_params[i]; | ||
| auto fragment_instance_id = local_params.fragment_instance_id; | ||
| _fragment_instance_ids.push_back(fragment_instance_id); | ||
| _fragment_instance_ids[i] = fragment_instance_id; | ||
| std::unique_ptr<RuntimeFilterMgr> runtime_filter_mgr; | ||
| auto init_runtime_state = [&](std::unique_ptr<RuntimeState>& runtime_state) { | ||
| runtime_state->set_query_mem_tracker(_query_ctx->query_mem_tracker); | ||
| @@ -588,7 +598,7 @@ Status PipelineXFragmentContext::_build_pipeline_tasks( | ||
| filterparams->runtime_filter_mgr = runtime_filter_mgr.get(); | ||
| _runtime_filter_states.push_back(std::move(filterparams)); | ||
| _runtime_filter_states[i] = std::move(filterparams); | ||
| std::map<PipelineId, PipelineXTask*> pipeline_id_to_task; | ||
| auto get_local_exchange_state = [&](PipelinePtr pipeline) | ||
| -> std::map<int, std::pair<std::shared_ptr<LocalExchangeSharedState>, | ||
| @@ -608,32 +618,30 @@ Status PipelineXFragmentContext::_build_pipeline_tasks( | ||
| } | ||
| return le_state_map; | ||
| }; | ||
| auto get_task_runtime_state = [&](int task_id) -> RuntimeState* { | ||
| DCHECK(_task_runtime_states[task_id]); | ||
| return _task_runtime_states[task_id].get(); | ||
| }; | ||
| for (size_t pip_idx = 0; pip_idx < _pipelines.size(); pip_idx++) { | ||
| auto& pipeline = _pipelines[pip_idx]; | ||
| if (pipeline->need_to_create_task()) { | ||
| if (pipeline->num_tasks() > 1 || i == 0) { | ||
| auto cur_task_id = _total_tasks++; | ||
| DCHECK(_task_runtime_states[pip_idx][i] == nullptr) | ||
| << print_id(_task_runtime_states[pip_idx][i]->fragment_instance_id()) << " " | ||
| << pipeline->debug_string(); | ||
| // build task runtime state | ||
| _task_runtime_states.push_back(RuntimeState::create_unique( | ||
| _task_runtime_states[pip_idx][i] = RuntimeState::create_unique( | ||
| this, local_params.fragment_instance_id, request.query_id, | ||
| request.fragment_id, request.query_options, _query_ctx->query_globals, | ||
| _exec_env, _query_ctx.get())); | ||
| auto& task_runtime_state = _task_runtime_states.back(); | ||
| _exec_env, _query_ctx.get()); | ||
| auto& task_runtime_state = _task_runtime_states[pip_idx][i]; | ||
| init_runtime_state(task_runtime_state); | ||
| auto cur_task_id = _total_tasks++; | ||
| task_runtime_state->set_task_id(cur_task_id); | ||
| task_runtime_state->set_task_num(pipeline->num_tasks()); | ||
| auto task = std::make_unique<PipelineXTask>( | ||
| pipeline, cur_task_id, get_task_runtime_state(cur_task_id), this, | ||
| pipeline_id_to_profile[pip_idx].get(), get_local_exchange_state(pipeline), | ||
| i); | ||
| auto task = std::make_unique<PipelineXTask>(pipeline, cur_task_id, | ||
| task_runtime_state.get(), ctx, | ||
| pipeline_id_to_profile[pip_idx].get(), | ||
| get_local_exchange_state(pipeline), i); | ||
| pipeline_id_to_task.insert({pipeline->id(), task.get()}); | ||
| _tasks[i].emplace_back(std::move(task)); | ||
| } | ||
| } | ||
| /** | ||
| * Build DAG for pipeline tasks. | ||
| * For example, we have | ||
| @@ -693,6 +701,40 @@ Status PipelineXFragmentContext::_build_pipeline_tasks( | ||
| std::lock_guard<std::mutex> l(_state_map_lock); | ||
| _runtime_filter_mgr_map[fragment_instance_id] = std::move(runtime_filter_mgr); | ||
| } | ||
| return Status::OK(); | ||
| }; | ||
| if (target_size > 1 && | ||
| (_runtime_state->query_options().__isset.parallel_prepare_threshold && | ||
| target_size > _runtime_state->query_options().parallel_prepare_threshold)) { | ||
| Status prepare_status[target_size]; | ||
| std::mutex m; | ||
| std::condition_variable cv; | ||
| int prepare_done = 0; | ||
| for (size_t i = 0; i < target_size; i++) { | ||
| RETURN_IF_ERROR(thread_pool->submit_func([&, i]() { | ||
| SCOPED_ATTACH_TASK(_query_ctx.get()); | ||
yiguolei marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| prepare_status[i] = pre_and_submit(i, this); | ||
| std::unique_lock<std::mutex> lock(m); | ||
| prepare_done++; | ||
| if (prepare_done == target_size) { | ||
| cv.notify_one(); | ||
| } | ||
| })); | ||
| } | ||
| std::unique_lock<std::mutex> lock(m); | ||
| if (prepare_done != target_size) { | ||
| cv.wait(lock); | ||
yiguolei marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| for (size_t i = 0; i < target_size; i++) { | ||
| if (!prepare_status[i].ok()) { | ||
| return prepare_status[i]; | ||
| } | ||
| } | ||
| } | ||
| } else { | ||
| for (size_t i = 0; i < target_size; i++) { | ||
| RETURN_IF_ERROR(pre_and_submit(i, this)); | ||
| } | ||
| } | ||
| _pipeline_parent_map.clear(); | ||
| _dag.clear(); | ||
| @@ -1512,8 +1554,12 @@ Status PipelineXFragmentContext::send_report(bool done) { | ||
| std::vector<RuntimeState*> runtime_states; | ||
| for (auto& task_state : _task_runtime_states) { | ||
| runtime_states.push_back(task_state.get()); | ||
| for (auto& task_states : _task_runtime_states) { | ||
| for (auto& task_state : task_states) { | ||
| if (task_state) { | ||
| runtime_states.push_back(task_state.get()); | ||
| } | ||
| } | ||
| } | ||
| return _report_status_cb( | ||
| {true, exec_status, runtime_states, nullptr, _runtime_state->load_channel_profile(), | ||
Uh oh!
There was an error while loading. Please reload this page.