mindspore2022/mindspore/ccsrc/pipeline/jit/pipeline_split.cc

136 lines
5.0 KiB
C++

/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string>
#include <memory>
#include "pipeline/jit/pipeline_split.h"
#include "utils/ms_context.h"
#include "utils/comm_manager.h"
#include "frontend/parallel/context.h"
#include "frontend/parallel/pipeline_transformer/pipeline_transformer.h"
#include "frontend/parallel/step_parallel.h"
namespace mindspore {
namespace pipeline {
std::string GetWorldGroup() {
auto ms_context = MsContext::GetInstance();
MS_EXCEPTION_IF_NULL(ms_context);
std::string world_group;
std::string backend = ms_context->get_param<std::string>(MS_CTX_DEVICE_TARGET);
if (backend == kAscendDevice) {
world_group = parallel::HCCL_WORLD_GROUP;
} else if (backend == kGPUDevice) {
world_group = parallel::NCCL_WORLD_GROUP;
} else {
MS_LOG(EXCEPTION) << "Invalid backend: " << backend;
}
return world_group;
}
static int64_t GetRank() {
auto ms_context = MsContext::GetInstance();
MS_EXCEPTION_IF_NULL(ms_context);
auto world_group = GetWorldGroup();
int64_t global_rank = parallel::ParallelContext::GetInstance()->global_rank();
uint32_t rank_id = 0;
if (!parallel::ParallelContext::GetInstance()->global_rank_is_set()) {
if (!CommManager::GetInstance().GetRankID(world_group, &rank_id)) {
MS_LOG(EXCEPTION) << "Get rank id failed.";
}
global_rank = UintToInt(rank_id);
}
return global_rank;
}
static int64_t InferStage(int64_t rank_id, int64_t stage_num, int64_t device_num) {
if (stage_num == 0) {
MS_LOG(EXCEPTION) << "stage_num is zero";
}
if (device_num % stage_num != 0) {
MS_LOG(EXCEPTION) << "Device_num must be divisible by the stage_num, got device_num: " << device_num
<< "stage_num: " << stage_num;
}
auto per_stage_rank_num = device_num / stage_num;
return rank_id / per_stage_rank_num;
}
// Only auto_parallel and semi_auto_parallel support PipelineSplit
bool PipelineSplit(const ResourcePtr &res) {
MS_EXCEPTION_IF_NULL(res);
auto parallel_mode = parallel::ParallelContext::GetInstance()->parallel_mode();
if (parallel_mode != parallel::SEMI_AUTO_PARALLEL && parallel_mode != parallel::AUTO_PARALLEL) {
MS_LOG(INFO) << "Only auto_parallel and semi_auto_parallel support pipeline split.";
return true;
}
auto stage_num = parallel::ParallelContext::GetInstance()->pipeline_stage_split_num();
if (stage_num <= 1) {
MS_LOG(INFO) << "The parameter 'stage_num' is: " << stage_num << ". No need Pipeline split.";
return true;
}
auto manager = res->manager();
auto root = res->func_graph();
auto global_rank = GetRank();
auto world_group = GetWorldGroup();
uint32_t world_rank_size = 0;
int64_t device_num = 0;
if (!parallel::ParallelContext::GetInstance()->device_num_is_set()) {
if (!CommManager::GetInstance().GetRankSize(world_group, &world_rank_size)) {
MS_LOG(EXCEPTION) << "Get rank size failed";
}
device_num = UintToInt(world_rank_size);
MS_LOG(INFO) << "Get device num from communication model, the device num is " << device_num;
} else {
device_num = parallel::ParallelContext::GetInstance()->device_num();
}
if (device_num < 1) {
MS_LOG(ERROR) << "The context configuration parameter 'device_num' must be positive, "
"but got the value of device_num: "
<< device_num;
}
if (global_rank < 0) {
MS_LOG(ERROR) << "The context configuration parameter 'global_rank' must be nonnegative, "
"but got the value of global_rank: "
<< global_rank;
}
auto stage = InferStage(global_rank, stage_num, device_num);
auto per_stage_rank_num = device_num / stage_num;
if (parallel::ParallelInit() != parallel::SUCCESS) {
MS_LOG(EXCEPTION) << "parallel init failed.";
}
auto transformer =
std::make_shared<parallel::PipelineTransformer>(manager, stage, root, global_rank, per_stage_rank_num);
// step1: Do color graph
transformer->Coloring();
transformer->MainGraph();
// step2: Do color broadcast
transformer->BroadCastColoring();
transformer->LabelMicroBatch();
// step3: Handle shared parameters
transformer->ParameterColoring();
// step4: Cut Graph
transformer->CutGraph();
// step5: Handle Sens
if (root->has_flag(parallel::TRAINING)) {
transformer->CoverSensShape();
}
// step6: Elim Graph stages and no used parameter
transformer->ElimGraphStage();
transformer->ElimParameter();
return true;
}
} // namespace pipeline
} // namespace mindspore