• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "compiler_logger.h"
17 #include "optimizer/ir/graph.h"
18 #include "optimizer/ir/basicblock.h"
19 #include "pass_manager_statistics.h"
20 
21 namespace panda::compiler {
PassManagerStatistics(Graph * graph)22 PassManagerStatistics::PassManagerStatistics(Graph *graph)
23     : graph_(graph),
24       pass_stat_list_(graph->GetAllocator()->Adapter()),
25       pass_stat_stack_(graph->GetAllocator()->Adapter()),
26       enable_ir_stat_(options.IsCompilerEnableIrStats())
27 {
28 }
29 
PrintStatistics() const30 void PassManagerStatistics::PrintStatistics() const
31 {
32     // clang-format off
33 #ifndef __clang_analyzer__
34     auto& out = std::cerr;
35     static constexpr size_t BUF_SIZE = 64;
36     static constexpr auto OFFSET_STAT = 2;
37     static constexpr auto OFFSET_ID = 4;
38     static constexpr auto OFFSET_DEFAULT = 12;
39     static constexpr auto OFFSET_PASS_NAME = 34;
40     static constexpr auto OFFSET_TOTAL = 41;
41     char space_buf[BUF_SIZE];
42     std::fill(space_buf, space_buf + BUF_SIZE, ' ');
43     size_t index = 0;
44     out << std::dec
45         << std::setw(OFFSET_ID) << std::right << "ID" << " " << std::left
46         << std::setw(OFFSET_PASS_NAME) << "Pass Name" << ": " << std::right
47         << std::setw(OFFSET_DEFAULT) << "IR mem" << std::right
48         << std::setw(OFFSET_DEFAULT) << "Local mem" << std::right
49         << std::setw(OFFSET_DEFAULT) << "Time,us" << std::endl;
50     out << "-----------------------------------------------------------------------------\n";
51     size_t total_time = 0;
52     for (const auto& stat : pass_stat_list_) {
53         auto indent = stat.run_depth * OFFSET_STAT;
54         space_buf[indent] = 0;
55         out << std::setw(OFFSET_ID) << std::right << index << space_buf << " " << std::left
56             << std::setw(OFFSET_PASS_NAME - indent) << stat.pass_name << ": " << std::right
57             << std::setw(OFFSET_DEFAULT) << stat.mem_used_ir << std::setw(OFFSET_DEFAULT)
58             << stat.mem_used_local << std::setw(OFFSET_DEFAULT) << stat.time_us << std::endl;
59         space_buf[indent] = ' ';
60         index++;
61         total_time += stat.time_us;
62     }
63     out << "-----------------------------------------------------------------------------\n";
64     out << std::setw(OFFSET_TOTAL) << "TOTAL: "
65         << std::right << std::setw(OFFSET_DEFAULT) << graph_->GetAllocator()->GetAllocatedSize()
66         << std::setw(OFFSET_DEFAULT) << graph_->GetLocalAllocator()->GetAllocatedSize()
67         << std::setw(OFFSET_DEFAULT) << total_time << std::endl;
68     out << "PBC instruction number : " << pbc_inst_num_ << std::endl;
69 #endif
70     // clang-format on
71 }
72 
ProcessBeforeRun(const Pass & pass)73 void PassManagerStatistics::ProcessBeforeRun(const Pass &pass)
74 {
75     size_t allocated_size = graph_->GetAllocator()->GetAllocatedSize();
76     constexpr auto OFFSET_NORMAL = 2;
77     std::string indent(pass_call_depth_ * OFFSET_NORMAL, '.');
78     COMPILER_LOG(DEBUG, PM) << "Run pass: " << indent << pass.GetPassName();
79 
80     if (!pass_stat_stack_.empty()) {
81         auto top_pass = pass_stat_stack_.top();
82         ASSERT(allocated_size >= last_allocated_ir_);
83         ASSERT(top_pass != nullptr);
84         top_pass->mem_used_ir += allocated_size - last_allocated_ir_;
85         if (!options.IsCompilerResetLocalAllocator()) {
86             ASSERT(graph_->GetLocalAllocator()->GetAllocatedSize() >= last_allocated_local_);
87             top_pass->mem_used_local += graph_->GetLocalAllocator()->GetAllocatedSize() - last_allocated_local_;
88         }
89         top_pass->time_us +=
90             std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - last_timestamp_)
91                 .count();
92     }
93 
94     pass_stat_list_.push_back({pass_call_depth_, pass.GetPassName(), {0, 0}, {0, 0}, 0, 0, 0});
95     if (enable_ir_stat_) {
96         for (auto block : graph_->GetVectorBlocks()) {
97             if (block == nullptr) {
98                 continue;
99             }
100             pass_stat_list_.back().before_pass.num_of_basicblocks++;
101             for ([[maybe_unused]] auto inst : block->Insts()) {
102                 pass_stat_list_.back().before_pass.num_of_instructions++;
103             }
104         }
105     }
106 
107     pass_stat_stack_.push(&pass_stat_list_.back());
108     // Call `GetAllocator()->GetAllocatedSize()` again to exclude allocations caused by PassManagerStatistics itself:
109     last_allocated_ir_ = graph_->GetAllocator()->GetAllocatedSize();
110     last_allocated_local_ = graph_->GetLocalAllocator()->GetAllocatedSize();
111     last_timestamp_ = std::chrono::steady_clock::now();
112 
113     pass_call_depth_++;
114 }
115 
ProcessAfterRun(size_t local_mem_used)116 void PassManagerStatistics::ProcessAfterRun(size_t local_mem_used)
117 {
118     auto top_pass = pass_stat_stack_.top();
119     ASSERT(graph_->GetAllocator()->GetAllocatedSize() >= last_allocated_ir_);
120     top_pass->mem_used_ir += graph_->GetAllocator()->GetAllocatedSize() - last_allocated_ir_;
121     if (options.IsCompilerResetLocalAllocator()) {
122         top_pass->mem_used_local = local_mem_used;
123     } else {
124         ASSERT(graph_->GetLocalAllocator()->GetAllocatedSize() >= last_allocated_local_);
125         top_pass->mem_used_local += graph_->GetLocalAllocator()->GetAllocatedSize() - last_allocated_local_;
126     }
127     top_pass->time_us +=
128         std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - last_timestamp_)
129             .count();
130 
131     if (enable_ir_stat_) {
132         for (auto block : graph_->GetVectorBlocks()) {
133             if (block == nullptr) {
134                 continue;
135             }
136             top_pass->after_pass.num_of_basicblocks++;
137             for ([[maybe_unused]] auto inst : block->Insts()) {
138                 top_pass->after_pass.num_of_instructions++;
139             }
140         }
141     }
142 
143     pass_stat_stack_.pop();
144     last_allocated_ir_ = graph_->GetAllocator()->GetAllocatedSize();
145     last_allocated_local_ = graph_->GetLocalAllocator()->GetAllocatedSize();
146     last_timestamp_ = std::chrono::steady_clock::now();
147 
148     pass_call_depth_--;
149     pass_run_index_++;
150 }
151 
DumpStatisticsCsv(char sep) const152 void PassManagerStatistics::DumpStatisticsCsv(char sep) const
153 {
154     ASSERT(options.WasSetCompilerDumpStatsCsv());
155     static std::ofstream csv(options.GetCompilerDumpStatsCsv(), std::ofstream::trunc);
156     auto m_name = graph_->GetRuntime()->GetMethodFullName(graph_->GetMethod(), true);
157     for (const auto &i : pass_stat_list_) {
158         csv << "\"" << m_name << "\"" << sep;
159         csv << i.pass_name << sep;
160         csv << i.mem_used_ir << sep;
161         csv << i.mem_used_local << sep;
162         csv << i.time_us << sep;
163         if (enable_ir_stat_) {
164             csv << i.before_pass.num_of_basicblocks << sep;
165             csv << i.after_pass.num_of_basicblocks << sep;
166             csv << i.before_pass.num_of_instructions << sep;
167             csv << i.after_pass.num_of_instructions << sep;
168         }
169         csv << GetPbcInstNum();
170         csv << '\n';
171     }
172     // Flush stream because it is declared `static`:
173     csv << std::flush;
174 }
175 }  // namespace panda::compiler
176