mindspore2022/mindspore/ccsrc/backend/common/pass/optimize_updatestate.cc

104 lines
3.8 KiB
C++

/**
* Copyright 2021 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 "backend/common/pass/optimize_updatestate.h"
#include <memory>
#include <vector>
#include <string>
#include "base/core_ops.h"
#include "include/common/utils/utils.h"
namespace mindspore {
namespace opt {
constexpr size_t kInputIndex = 1;
constexpr size_t kAttachIndex = 2;
constexpr size_t kAdditionalAttachIndex = 3;
/**
* @brief Define a pattern for the OptimizeUpdateState.
*
* This function defines a pattern with the prim::kPrimUpdateState primitive followed by a sequence variable.
*
* @return A VectorRef representing the defined pattern.
*/
const BaseRef OptimizeUpdateState::DefinePattern() const {
// Create a sequence variable.
VarPtr Xs = std::make_shared<SeqVar>();
return VectorRef({prim::kPrimUpdateState, Xs});
}
/**
* @brief Processes the given node to optimize UpdateState operations.
*
* This function optimizes UpdateState operations by reducing unnecessary attach nodes. If the attach node is only used
* by the UpdateState operation and is not a parameter, it will be dropped. If there are changes in the attaches, a new
* UpdateState node will be created with the optimized attaches.
*
* @param func_graph The current function graph.
* @param node The node to be processed.
* @param EquivPtr Placeholder for equivalence. Not used in this context.
* @return An optimized AnfNodePtr if applicable, or nullptr if no optimization was applied.
*/
const AnfNodePtr OptimizeUpdateState::Process(const FuncGraphPtr &func_graph, const AnfNodePtr &node,
const EquivPtr &) const {
// Ensure func_graph and node are not null.
MS_EXCEPTION_IF_NULL(func_graph);
MS_EXCEPTION_IF_NULL(node);
// Cast the node to a CNode.
auto update_state = dyn_cast<CNode>(node);
MS_EXCEPTION_IF_NULL(update_state);
// If the UpdateState node doesn't have additional attaches, skip processing.
if (update_state->size() <= kAdditionalAttachIndex) {
return nullptr;
}
auto manager = func_graph->manager();
MS_EXCEPTION_IF_NULL(manager);
auto &node_users = manager->node_users();
std::vector<AnfNodePtr> new_inputs;
(void)new_inputs.emplace_back(update_state->input(0));
(void)new_inputs.emplace_back(update_state->input(kInputIndex));
(void)new_inputs.emplace_back(update_state->input(kAttachIndex));
// Process each attach and decide whether to keep it.
for (size_t i = kAdditionalAttachIndex; i < update_state->size(); ++i) {
auto &attach = update_state->input(i);
auto &users = node_users[attach];
if ((users.size() == 1) && (users.front().first == update_state) && !attach->isa<Parameter>()) {
// If the only user of attach is the UpdateState node and it's not a parameter, skip adding this attach.
continue;
}
(void)new_inputs.emplace_back(attach);
}
// If there were no changes in the attaches, return nullptr.
if (new_inputs.size() == update_state->size()) {
return nullptr;
}
// If the attaches changed, create a new UpdateState node.
auto new_update_state = func_graph->NewCNode(new_inputs);
new_update_state->set_abstract(update_state->abstract());
new_update_state->set_scope(update_state->scope());
return new_update_state;
}
} // namespace opt
} // namespace mindspore