!13834 [GraphKernel] Remove two graph kernel frontend pass
From: @tronzhang Reviewed-by: @gaoxiong1,@gaoxiong1,@dylangeng Signed-off-by: @dylangengpull/13834/MERGE
commit
a06234ed13
@ -1 +1 @@
|
||||
Subproject commit 78799c123d966ce78ae7c9f6860264628262a16e
|
||||
Subproject commit 1b0aacec7c125083dbe9fd54174495f92f6bb191
|
@ -1,152 +0,0 @@
|
||||
/**
|
||||
* 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 "frontend/optimizer/graph_kernel_reuse.h"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "ir/graph_utils.h"
|
||||
|
||||
namespace mindspore {
|
||||
/* namespace to support opt */
|
||||
namespace opt {
|
||||
bool GraphKernelReuse::CompareNode(const AnfNodePtr a, const AnfNodePtr b) {
|
||||
if (a->abstract() && b->abstract()) {
|
||||
auto a_type = a->abstract()->GetTypeTrack();
|
||||
auto b_type = b->abstract()->GetTypeTrack();
|
||||
if (a_type != b_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto a_shape = a->abstract()->GetShapeTrack();
|
||||
auto b_shape = b->abstract()->GetShapeTrack();
|
||||
if (a_shape != nullptr && a_shape == b_shape) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a_shape != nullptr && b_shape != nullptr && a_shape->isa<abstract::Shape>() &&
|
||||
b_shape->isa<abstract::Shape>()) {
|
||||
return a_shape->cast<abstract::ShapePtr>()->shape() == b_shape->cast<abstract::ShapePtr>()->shape();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GraphKernelReuse::DoReplace(const FuncGraphManagerPtr manager) {
|
||||
bool changed = false;
|
||||
auto fgs = manager->func_graphs();
|
||||
for (FuncGraphPtr &fg : fgs) {
|
||||
if (!fg->has_attr(FUNC_GRAPH_ATTR_GRAPH_KERNEL)) {
|
||||
continue;
|
||||
}
|
||||
std::string key = GetValue<std::string>(fg->get_attr(FUNC_GRAPH_ATTR_GRAPH_KERNEL));
|
||||
if (graph_kernel_ops.find(key) != graph_kernel_ops.end()) {
|
||||
if (find(graph_kernel_ops[key].begin(), graph_kernel_ops[key].end(), fg) == graph_kernel_ops[key].end()) {
|
||||
FuncGraphPtr new_fg = nullptr;
|
||||
for (auto &cfg : graph_kernel_ops[key]) {
|
||||
// If two graphs have different size then continue
|
||||
auto fg_topos = TopoSort(fg->get_return());
|
||||
auto cfg_topos = TopoSort(cfg->get_return());
|
||||
if (fg_topos.size() != cfg_topos.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compare const tensor
|
||||
bool has_same = true;
|
||||
for (size_t i = 0; i < fg_topos.size(); ++i) {
|
||||
if (IsValueNode<tensor::Tensor>(fg_topos[i])) {
|
||||
if (!IsValueNode<tensor::Tensor>(cfg_topos[i])) {
|
||||
has_same = false;
|
||||
break;
|
||||
}
|
||||
|
||||
auto tensor1 = GetValueNode<tensor::TensorPtr>(fg_topos[i]);
|
||||
auto tensor2 = GetValueNode<tensor::TensorPtr>(cfg_topos[i]);
|
||||
if (!tensor1->ValueEqual(*tensor2)) {
|
||||
has_same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_same) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto fg_input = fg->parameters();
|
||||
auto cfg_input = cfg->parameters();
|
||||
if (fg_input.size() != cfg_input.size()) {
|
||||
continue;
|
||||
}
|
||||
// Compare input
|
||||
for (size_t i = 0; i < fg_input.size(); ++i) {
|
||||
if (!CompareNode(fg_input[i], cfg_input[i])) {
|
||||
has_same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_same) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compare output
|
||||
if (!CompareNode(fg->output(), cfg->output())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find reusable fg
|
||||
new_fg = cfg;
|
||||
break;
|
||||
}
|
||||
|
||||
if (new_fg != nullptr) {
|
||||
// Replace current fg with existing fg
|
||||
auto users = fg->func_graph_cnodes_index();
|
||||
for (auto &iter : users) {
|
||||
auto cnode = iter.first->first->cast<CNodePtr>();
|
||||
auto new_input = cnode->inputs();
|
||||
auto main_graph = cnode->func_graph();
|
||||
MS_EXCEPTION_IF_NULL(main_graph);
|
||||
if (IsPrimitiveCNode(cnode, prim::kPrimPartial)) {
|
||||
new_input[1] = NewValueNode(new_fg);
|
||||
} else {
|
||||
new_input[0] = NewValueNode(new_fg);
|
||||
}
|
||||
auto new_cnode = main_graph->NewCNode(new_input);
|
||||
manager->Replace(iter.first->first, new_cnode);
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
// Add current fg to map
|
||||
graph_kernel_ops[key].push_back(fg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
graph_kernel_ops[key] = {fg};
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool GraphKernelReuse::ReuseGraphKernel(const FuncGraphPtr root, const FuncGraphManagerPtr manager) {
|
||||
MS_EXCEPTION_IF_NULL(manager);
|
||||
manager->AddFuncGraph(root);
|
||||
|
||||
return DoReplace(manager);
|
||||
}
|
||||
} // namespace opt
|
||||
} // namespace mindspore
|
@ -1,50 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MINDSPORE_CCSRC_FRONTEND_OPTIMIZER_GRAPH_KERNEL_OP_REUSE_H
|
||||
#define MINDSPORE_CCSRC_FRONTEND_OPTIMIZER_GRAPH_KERNEL_OP_REUSE_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "mindspore/ccsrc/backend/session/anf_runtime_algorithm.h"
|
||||
#include "frontend/optimizer/optimizer.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace opt {
|
||||
// Common subexpression elimination.
|
||||
class GraphKernelReuse {
|
||||
public:
|
||||
GraphKernelReuse() : count(0) {}
|
||||
virtual ~GraphKernelReuse() = default;
|
||||
|
||||
bool operator()(const FuncGraphPtr &root, const OptimizerPtr &optimizer) {
|
||||
bool chg = ReuseGraphKernel(root, optimizer->resource()->manager());
|
||||
return chg;
|
||||
}
|
||||
|
||||
bool CompareNode(const AnfNodePtr a, const AnfNodePtr other);
|
||||
bool DoReplace(const FuncGraphManagerPtr manager);
|
||||
|
||||
bool ReuseGraphKernel(const FuncGraphPtr root, const FuncGraphManagerPtr manager);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::vector<FuncGraphPtr>> graph_kernel_ops;
|
||||
int64_t count;
|
||||
};
|
||||
} // namespace opt
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CCSRC_FRONTEND_OPTIMIZER_GRAPH_KERNEL_OP_REUSE_H
|
@ -1,84 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MINDSPORE_CCSRC_FRONTEND_OPTIMIZER_IRPASS_MARK_INTERFACE_FUSION_H
|
||||
#define MINDSPORE_CCSRC_FRONTEND_OPTIMIZER_IRPASS_MARK_INTERFACE_FUSION_H
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "backend/session/anf_runtime_algorithm.h"
|
||||
#include "frontend/optimizer/optimizer.h"
|
||||
#include "frontend/optimizer/irpass.h"
|
||||
#include "frontend/optimizer/anf_visitor.h"
|
||||
#include "frontend/operator/ops.h"
|
||||
#include "ir/graph_utils.h"
|
||||
#include "frontend/operator/composite/composite.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace opt {
|
||||
namespace irpass {
|
||||
static int64_t count = 0;
|
||||
|
||||
std::string GetFusionNumber() {
|
||||
std::stringstream ss;
|
||||
ss << std::setw(4) << std::setfill('0') << count;
|
||||
std::string num = ss.str();
|
||||
++count;
|
||||
|
||||
return "_" + num;
|
||||
}
|
||||
|
||||
// Mark CNodes which can be merged in kernel build
|
||||
class MarkInterfaceFusion : public AnfVisitor {
|
||||
public:
|
||||
AnfNodePtr operator()(const OptimizerPtr &, const AnfNodePtr &node) override {
|
||||
if (node->func_graph()->has_attr(FUNC_GRAPH_ATTR_GRAPH_KERNEL) && IsPrimitiveCNode(node, prim::kPrimSelect)) {
|
||||
auto cnode = node->cast<CNodePtr>();
|
||||
auto condition = cnode->input(1);
|
||||
std::string cmp;
|
||||
std::unordered_map<std::string, std::string> cmp_list = {{"GreaterEqual", "GE"}, {"Greater", "GT"},
|
||||
{"LessEqual", "LE"}, {"Less", "LT"},
|
||||
{"Equal", "EQ"}, {"NotEqual", "NE"}};
|
||||
if (IsPrimitiveCNode(condition)) {
|
||||
auto prim_name = GetCNodeFuncName(condition->cast<CNodePtr>());
|
||||
if (cmp_list.count(prim_name) != 0) {
|
||||
// Mark Select and compare node
|
||||
cmp = cmp_list[prim_name];
|
||||
auto cnt = GetFusionNumber();
|
||||
AnfAlgo::SetNodeAttr("fusion", MakeValue("Select" + cmp + cnt), condition);
|
||||
AnfAlgo::SetNodeAttr("fusion", MakeValue("Select" + cmp + cnt + "_end"), node);
|
||||
for (size_t i = 1; i < cnode->inputs().size(); ++i) {
|
||||
if (IsPrimitiveCNode(cnode->input(i), prim::kPrimZerosLike)) {
|
||||
AnfAlgo::SetNodeAttr("fusion", MakeValue("Select" + cmp + cnt), cnode->input(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Visit(const AnfNodePtr &) override {}
|
||||
|
||||
private:
|
||||
AnfNodePtr y_{nullptr};
|
||||
};
|
||||
} // namespace irpass
|
||||
} // namespace opt
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CCSRC_FRONTEND_OPTIMIZER_IRPASS_MARK_INTERFACE_FUSION_H
|
Loading…
Reference in new issue