forked from huawei/mindspore2022
222 lines
11 KiB
C++
222 lines
11 KiB
C++
/**
|
|
* Copyright 2019 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.
|
|
*/
|
|
|
|
#ifndef MINDSPORE_CCSRC_PARALLEL_AUTO_PARALLEL_GRAPH_COSTMODEL_H_
|
|
#define MINDSPORE_CCSRC_PARALLEL_AUTO_PARALLEL_GRAPH_COSTMODEL_H_
|
|
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
#include "../../common.h"
|
|
#include "common/utils.h"
|
|
#include "parallel/auto_parallel/edge_costmodel.h"
|
|
#include "parallel/costmodel_context.h"
|
|
#include "parallel/ops_info/operator_info.h"
|
|
#include "parallel/ops_info/tmp_identity_info.h"
|
|
|
|
namespace mindspore {
|
|
namespace parallel {
|
|
#define OPERATOR_TO_OPERATOR_CONNECTOR "-"
|
|
#define DEFAULT_DEVICE_MEMORY_CAPACITY (1024.0 * 1024.0 * 1024.0 * 16.0)
|
|
#define DEFAULT_COST_MODEL_ALPHA 1.0
|
|
#define DEFAULT_COST_MODEL_BETA 400.0
|
|
#define DEFAULT_COST_MODEL_GAMMA 0.001
|
|
#define DEFAULT_COST_MODEL_SIMPLIFY_CALCULATION true
|
|
#define DEFAULT_COST_MODEL_COMMUNI_THRESHOLD 2048.0
|
|
#define DEFAULT_COST_MODEL_COMMUNI_CONST 3072.0
|
|
#define DEFAULT_COST_MODEL_COMMUNI_BIAS 1024.0
|
|
#define DEFAULT_TENSOR_SLICE_ALIGNMENT_ENABLE false
|
|
#define DEFAULT_TENSOR_SLICE_ALIGNMENT_SIZE 16
|
|
#define DEFAULT_FULLY_USE_DEVICES true
|
|
#define DEFAULT_ELEMENTWISE_OP_STRA_FOLLOW false
|
|
#define DEFAULT_IS_MULTI_SUBGRAPHS false
|
|
|
|
class CostGraph;
|
|
using CostGraphPtr = std::shared_ptr<CostGraph>;
|
|
extern CostGraphPtr entire_costgraph;
|
|
extern size_t TOTAL_OPS;
|
|
extern double COST_MODEL_GAMMA;
|
|
extern bool COST_MODEL_SIMPLIFY_CALCULATION;
|
|
extern double DEVICE_MEMORY_CAPACITY;
|
|
extern double COST_MODEL_COMMUNI_THRESHOLD;
|
|
extern double COST_MODEL_COMMUNI_CONST;
|
|
extern double COST_MODEL_COMMUNI_BIAS;
|
|
extern bool TENSOR_SLICE_ALIGNMENT_ENABLE;
|
|
extern size_t TENSOR_SLICE_ALIGNMENT_SIZE;
|
|
extern bool FULLY_USE_DEVICES;
|
|
extern bool ELEMENTWISE_OP_STRA_FOLLOW;
|
|
|
|
class CostGraph {
|
|
// 'CostGraph' consists of Operators and edges between them. An edge is created between two Operators if they have
|
|
// output-input dependency relationship.
|
|
public:
|
|
CostGraph() {
|
|
dev_memory_ = DEFAULT_DEVICE_MEMORY_CAPACITY;
|
|
costmodel_alpha_ = DEFAULT_COST_MODEL_ALPHA;
|
|
costmodel_beta_ = DEFAULT_COST_MODEL_BETA;
|
|
}
|
|
~CostGraph() = default;
|
|
void AddOperator(const OperatorInfoPtr &op) { ops_.push_back(op); }
|
|
OperatorInfoPtr FindOperatorByIndex(size_t index) {
|
|
if (index >= ops_.size()) {
|
|
MS_LOG(ERROR) << "The index: " << index << " is out of the range of ops_: " << ops_.size() << ".";
|
|
return nullptr;
|
|
}
|
|
return ops_[index];
|
|
}
|
|
void RemoveOperator(const OperatorInfoPtr &op);
|
|
bool IsOperatorInCostGraph(const OperatorInfoPtr &op);
|
|
// the edge is in the form: u --> v
|
|
void AddEdge(OperatorInfoPtr u_node, OperatorInfoPtr v_node, const EdgePtr &edge) {
|
|
std::vector<EdgePtr> curr_edges(edges_[{u_node, v_node}]);
|
|
curr_edges.push_back(edge);
|
|
edges_[{u_node, v_node}] = curr_edges;
|
|
}
|
|
// An edge is uniquely identified by its name, and its output index and input index.
|
|
bool IsEdgeInCostGraph(const std::string &, size_t, size_t);
|
|
|
|
void SetDeviceMemoryAndCostParameter();
|
|
|
|
std::vector<std::shared_ptr<CostGraph>> ConstructConnectedComponents(std::vector<OperatorInfoPtr>);
|
|
void DFS(const OperatorInfoPtr ¤t_op, std::map<OperatorInfoPtr, bool> *visited,
|
|
const std::shared_ptr<CostGraph> &component);
|
|
|
|
CostPtrList CreateFinalCostList(const OperatorInfoPtr &u, const EdgePtr &e, const OperatorInfoPtr &v);
|
|
CostPtrList CreateFinalSingleCostList(const OperatorInfoPtr &u);
|
|
CostPtr SelectCostWithMemoryConstraint(const CostPtrList &cost_list, double memory);
|
|
CostPtr SelectCostWithMinTrainingTime(const CostPtrList &cost_list, double memory);
|
|
CostPtrList SelectCostListWithMinTrainingTimeMultiple(const std::vector<CostPtrList> &all_costlist, double memory);
|
|
Status SearchStrategyForMultiNodeFinalGraph(const std::vector<OperatorInfoPtr> &);
|
|
std::vector<std::shared_ptr<Edge>> GetOriginalEdgeBetweenOperators(OperatorInfoPtr u_node, OperatorInfoPtr v_node) {
|
|
return edges_[{u_node, v_node}];
|
|
}
|
|
double GetDeviceMemory() const { return dev_memory_; }
|
|
|
|
// Search the cost_list in the final graph, and determine the optimal one
|
|
Status SearchStrategy();
|
|
|
|
// Given a graph which contains the following subgraph: u --> v --> w, the node v can be eliminated
|
|
OperatorInfoPtr CheckOpElimination() const;
|
|
// Given a graph which contains the following subgraph where there are multiple edges between u and v, these edges
|
|
// can be eliminated into one
|
|
std::vector<EdgePtr> CheckEdgeElimination() const;
|
|
// Given a graph which contains the following subgraph:
|
|
// u
|
|
// |
|
|
// w --- v --- x
|
|
// where u has 0 incoming edge, u has 1 outgoing edge, and v has > 1 incoming edges, u can be merged into v.
|
|
// u is returned.
|
|
OperatorInfoPtr CheckMergeElimination() const;
|
|
// Given a graph which contains the following subgraph:
|
|
// u
|
|
// |
|
|
// v --- x
|
|
// where v has 2 outgoing edges, and u has 1 incoming edges and no outgoing edges. In this case, u can be contracted
|
|
// into v. u is returned.
|
|
OperatorInfoPtr CheckContractElimination() const;
|
|
/* Given a graph which contains the following subgraph:
|
|
* u
|
|
* / \
|
|
* / \
|
|
* v --- w
|
|
* where u has 2 outgoing edges, v has 1 outgoing edge, and w has 2 incoming edges, u can be eliminated into v.
|
|
* The returned value includes u and the edge <u, <v, w>>.
|
|
*/
|
|
std::pair<OperatorInfoPtr, EdgePtr> CheckTriangleElimination() const;
|
|
/* Given a graph which contains the following subgraph:
|
|
* v <--- u ---> w
|
|
* where u has 0 incoming edges, and multiple outgoing edges. In addition, v and w have other complicated connections,
|
|
* resulting in v and w can not be performed ContractElimination. u is returned.
|
|
* NOTE: this elimination MUST be performed only when the above 5 operation cannot be applied.
|
|
*/
|
|
OperatorInfoPtr CheckStarElimination() const;
|
|
// Applying Operator Elimination in DP algorithm
|
|
EdgePtr EliminationOp(const OperatorInfoPtr &op);
|
|
// Applying Edge Elimination in DP algorithm
|
|
EdgePtr EliminationEdges(const std::vector<EdgePtr> &edges);
|
|
// Applying Merge Elimination in DP algorithm
|
|
OperatorInfoPtr EliminationMerge(const OperatorInfoPtr &op);
|
|
void CreateMergeEliminationSubCostList(StrategyPtr op_strategy, const CostPtrList &op_cost_list,
|
|
const CostPtrList &edge_cost_list, StrategyPtr tar_op_strategy,
|
|
const CostPtrList &tar_cost_list, CostPtrList *tar_cost_list_new);
|
|
// Applying Contract Elimination in DP algorithm
|
|
OperatorInfoPtr EliminationContract(const OperatorInfoPtr &op);
|
|
void CreateContractEliminationSubCostList(StrategyPtr, const CostPtrList &, const CostPtrList &, StrategyPtr,
|
|
const CostPtrList &, CostPtrList *);
|
|
|
|
// Applying Triangle Elimination in DP algorithm. return the left_node
|
|
OperatorInfoPtr EliminationTriangle(const OperatorInfoPtr &elimi_op, const EdgePtr &edge_left_right);
|
|
void CreateTriangleEliminationCostList(const OperatorInfoPtr &, const CostPtrList &, const CostPtrList &,
|
|
const StrategyPtr &, const StrategyPtr &, const StrategyPtr &,
|
|
const CostPtrList &, const CostPtrList &, const CostPtrList &, CostPtrList *);
|
|
// Given the relevant costlist, create the TriangleElimination cost
|
|
void CreateTriangleEliminationSubCostList(StrategyPtr, StrategyPtr, StrategyPtr, const CostPtr &, const CostPtrList &,
|
|
const CostPtrList &, const CostPtr &, const CostPtrList &, CostPtrList *);
|
|
|
|
// Applying the Star Elimination in DP algorithm. Return the successive edges of this merged_op
|
|
// NOTE: this elimination MUST be performed only when the above 5 operation cannot be applied.
|
|
std::vector<EdgePtr> EliminationStar(const OperatorInfoPtr &op);
|
|
void CreateStarEliminationCostList(std::vector<EdgePtr> &, const StrategyPtr &, const CostPtrList &,
|
|
const CostPtrList &, const StrategyPtr &, const CostPtrList &, CostPtrList *);
|
|
void CreateStarEliminationSubCostList(const StrategyPtr &, const CostPtrList &, const CostPtrList &,
|
|
const StrategyPtr &, const CostPtrList &, std::vector<StrategyPtr>,
|
|
CostPtrList &, CostPtrList &, CostPtrList *);
|
|
// When the input of a operator is neither a WEIGHT, nor a output of a subsequent operator involving WEIGHT, then
|
|
// the memory cost can be resused.
|
|
Status CalculateOpsMemoryCost();
|
|
// When the input of the edge is neither a WEIGHT, nor a output of a subsequent operator involving WEIGHT, then
|
|
// the memory cost can be resused.
|
|
Status CalculateEdgesMemoryCost();
|
|
Status ComputeOpsAndEdgesParameterInvolved();
|
|
|
|
std::vector<OperatorInfoPtr> GetOperators() const { return ops_; }
|
|
size_t GetNumPairs() const { return edges_.size(); }
|
|
Status InitSelectedStrategy();
|
|
OperatorInfoPtr FindTmpIdentityByParameterName(std::string &) const;
|
|
// When TmpIdentity is used by mulitple operators, the corresponding parameter's memory cost should be calculated only
|
|
// once (instead of multiple times), this method is used to correct this.
|
|
Status CorrectOpsMemoryCost();
|
|
// Needed by rec_parser
|
|
void add_inputs_tensor_name(const std::vector<std::string> &inputs_tensor_name) {
|
|
inputs_tensor_name_list_.push_back(inputs_tensor_name);
|
|
}
|
|
const std::vector<std::vector<std::string>> get_inputs_tensor_name_list() const { return inputs_tensor_name_list_; }
|
|
void add_tuple_getitem(const std::pair<std::string, std::string> &tuple_getitem) {
|
|
auto ret = tuple_getitem_list_.insert(tuple_getitem);
|
|
if (ret.second == false) {
|
|
MS_LOG(EXCEPTION) << "The insert item is already exist.";
|
|
}
|
|
}
|
|
const std::map<std::string, std::string> get_tuple_getitem_list() const { return tuple_getitem_list_; }
|
|
|
|
private:
|
|
// Needed by rec_parser
|
|
std::vector<std::vector<std::string>> inputs_tensor_name_list_;
|
|
std::map<std::string, std::string> tuple_getitem_list_;
|
|
double dev_memory_;
|
|
double costmodel_alpha_;
|
|
double costmodel_beta_;
|
|
std::vector<OperatorInfoPtr> ops_;
|
|
std::map<std::pair<OperatorInfoPtr, OperatorInfoPtr>, std::vector<EdgePtr>> edges_;
|
|
std::vector<std::shared_ptr<CostGraph>> connected_compoents_;
|
|
};
|
|
} // namespace parallel
|
|
} // namespace mindspore
|
|
|
|
#endif // MINDSPORE_CCSRC_PARALLEL_AUTO_PARALLEL_GRAPH_COSTMODEL_H_
|