• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2019-2023 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "ir/func_graph_base.h"
17 
18 #include <list>
19 #include <algorithm>
20 #include "ir/func_graph.h"
21 #include "ir/meta_func_graph.h"
22 
23 namespace mindspore {
~FuncGraphLoopBreaker()24 FuncGraphLoopBreaker::~FuncGraphLoopBreaker() {
25   std::lock_guard<std::mutex> lock_set(func_mutex_);
26   for (auto fg : func_set_) {
27     MS_EXCEPTION_IF_NULL(fg);
28     fg->reg_flg_ = false;
29   }
30 }
31 
Inst()32 FuncGraphLoopBreaker &FuncGraphLoopBreaker::Inst() {
33   static FuncGraphLoopBreaker mgr;
34   return mgr;
35 }
36 
GetChecker(const std::string & checker_name)37 MS_CORE_API const FuncGraphChecker &FuncGraphBase::GetChecker(const std::string &checker_name) {
38   auto it = checkers_.find(checker_name);
39   if (it == checkers_.cend()) {
40     static const auto empty_checker = FuncGraphChecker();
41     return empty_checker;
42   }
43   return *(it->second);
44 }
45 
AddChecker(const std::string & checker_name,const std::shared_ptr<FuncGraphChecker> & new_checker)46 MS_CORE_API void FuncGraphBase::AddChecker(const std::string &checker_name,
47                                            const std::shared_ptr<FuncGraphChecker> &new_checker) {
48   (void)checkers_.emplace(checker_name, new_checker);
49 }
50 
BreakLoop()51 void FuncGraphLoopBreaker::BreakLoop() {
52   MS_LOG(INFO) << "Size of not recycled graph before break loop is:" << func_set_.size();
53   std::list<FuncGraphBasePtr> func_list;
54 
55   // Generate shared_ptr for every graph, to avoid func_set_ changes while BreakLoop
56   (void)std::for_each(func_set_.begin(), func_set_.end(), [&func_list](FuncGraphBase *fun) {
57     if (fun != nullptr && !fun->subclass_destruct_flag_) {
58       (void)func_list.emplace_back(fun->shared_from_base<FuncGraphBase>());
59     }
60   });
61   for (auto &item : func_list) {
62     if (item == nullptr) {
63       continue;
64     }
65     item->DoBreakLoop();
66   }
67   func_list.clear();
68 
69   int func_graph_cnt = 0;
70   for (auto item : func_set_) {
71     if (item->isa<FuncGraph>()) {
72       MS_LOG(INFO) << "Unfree graph info:" << item->ToString();
73       func_graph_cnt++;
74     }
75   }
76   if (func_graph_cnt > 0) {
77     MS_LOG(INFO) << "Size of not recycled graph after break loop should be 0, but got: " << func_graph_cnt << "\n"
78                  << "Please check the usage of clear_compile_cache or contact to the maintenance engineers.";
79   }
80 }
81 
Dump() const82 void FuncGraphLoopBreaker::Dump() const {
83   MS_LOG(INFO) << "Total func graphs: " << func_set_.size();
84   for (const auto &fun : func_set_) {
85     if (fun != nullptr && !fun->subclass_destruct_flag_) {
86       const auto &f = fun->shared_from_base<FuncGraphBase>();
87       auto use_count = f.use_count();
88       const auto &fg = dyn_cast<FuncGraph>(f);
89       MS_LOG(INFO) << "FuncGraph: " << f << "/" << f->ToString() << ", use_count: " << use_count
90                    << (fg != nullptr ? (std::string(", attached_mng_cnt: ") + std::to_string(fg->attached_mng_cnt()))
91                                      : "")
92                    << ", type: " << f->type_name();
93     }
94   }
95 }
96 
CleanMetaFuncGraphs()97 void FuncGraphLoopBreaker::CleanMetaFuncGraphs() {
98   std::list<FuncGraphBasePtr> func_list;
99   // Generate shared_ptr for every graph, to avoid func_set_ changes while BreakLoop
100   (void)std::for_each(func_set_.begin(), func_set_.end(), [&func_list](FuncGraphBase *fun) {
101     if (fun != nullptr && !fun->subclass_destruct_flag_) {
102       (void)func_list.emplace_back(fun->shared_from_base<FuncGraphBase>());
103     }
104   });
105   for (auto item : func_list) {
106     if (item == nullptr) {
107       continue;
108     }
109     if (item->isa<MetaFuncGraph>()) {
110       item->DoBreakLoop();
111     }
112   }
113 }
114 
115 // If phase is empty, clean all collected func graphs.
CleanUnusedFuncGraphs(const std::string & phase)116 void FuncGraphLoopBreaker::CleanUnusedFuncGraphs(const std::string &phase) {
117   std::list<FuncGraphBasePtr> func_list;
118   // Generate shared_ptr for every graph, to avoid func_set_ changes while BreakLoop
119   (void)std::for_each(func_set_.begin(), func_set_.end(), [&func_list](FuncGraphBase *fun) {
120     if (fun != nullptr && !fun->subclass_destruct_flag_) {
121       (void)func_list.emplace_back(fun->shared_from_base<FuncGraphBase>());
122     }
123   });
124   for (auto item : func_list) {
125     if (item == nullptr) {
126       continue;
127     }
128     const auto &fg = dyn_cast<FuncGraph>(item);
129     if (fg == nullptr || !fg->IsSameTypeId(FuncGraph::kTypeId)) {
130       continue;
131     }
132     if (!phase.empty() && fg->phase() != phase) {
133       continue;
134     }
135     MS_LOG(INFO) << "Drop " << fg << "/" << fg->ToString() << ", use_count: " << fg.use_count()
136                  << ", type: " << fg->type_name();
137     fg->ResetReturnOwner();
138     fg->ResetOwnNodes();
139     fg->set_dropped(true);
140   }
141 }
142 
ClearCellGraphs(const std::string & phase)143 void FuncGraphLoopBreaker::ClearCellGraphs(const std::string &phase) {
144   std::list<FuncGraphBasePtr> func_list;
145   // Generate shared_ptr for every graph, to avoid func_set_ changes while BreakLoop
146   (void)std::for_each(func_set_.begin(), func_set_.end(), [&func_list](FuncGraphBase *fun) {
147     if (fun != nullptr && !fun->subclass_destruct_flag_) {
148       (void)func_list.emplace_back(fun->shared_from_base<FuncGraphBase>());
149     }
150   });
151   for (auto item : func_list) {
152     if (item != nullptr && item->isa<FuncGraph>()) {
153       auto func_graph = item->cast<FuncGraphPtr>();
154       if (func_graph != nullptr && func_graph->phase() == phase) {
155         func_graph->DoBreakLoop();
156       }
157     }
158   }
159 }
160 }  // namespace mindspore
161