• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2016 The TensorFlow Authors All Rights Reserved.
2 
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 "tensorflow/core/profiler/internal/tfprof_show.h"
17 
18 #include <memory>
19 #include <set>
20 
21 #include "absl/strings/str_format.h"
22 #include "absl/strings/str_join.h"
23 #include "tensorflow/core/platform/env.h"
24 #include "tensorflow/core/platform/regexp.h"
25 
26 namespace tensorflow {
27 namespace tfprof {
28 
Show(const string & prefix,const Options & opts)29 const GraphNodeProto& TFShow::Show(const string& prefix, const Options& opts) {
30   if (opts.output_type == kOutput[0]) {
31     Timeline timeline(opts.step, opts.output_options.at(kTimelineOpts[0]));
32     return ShowInternal(opts, &timeline)->proto();
33   } else {
34     const ShowNode* ret = ShowInternal(opts, nullptr);
35     if (opts.output_type == kOutput[1]) {
36       absl::PrintF("%s", (prefix + ret->formatted_str));
37       fflush(stdout);
38     } else if (opts.output_type == kOutput[2]) {
39       Status s = WriteStringToFile(Env::Default(),
40                                    opts.output_options.at(kFileOpts[0]),
41                                    prefix + ret->formatted_str);
42       if (!s.ok()) {
43         absl::FPrintF(stderr, "%s\n", s.ToString());
44       }
45     } else if (opts.output_type == kOutput[3] ||
46                opts.output_type == kOutput[4]) {
47     } else {
48       absl::FPrintF(stderr, "Unknown output type: %s\n", opts.output_type);
49     }
50     return ret->proto();
51   }
52 }
53 
LookUpCheckPoint(const string & name,std::unique_ptr<TFProfTensor> * tensor)54 bool TFShow::LookUpCheckPoint(const string& name,
55                               std::unique_ptr<TFProfTensor>* tensor) {
56   if (name == kTFProfRoot || !ckpt_reader_ || !tensor) {
57     return false;
58   }
59   std::unique_ptr<Tensor> out_tensor;
60   TF_Status* status = TF_NewStatus();
61   ckpt_reader_->GetTensor(name, &out_tensor, status);
62   if (TF_GetCode(status) != TF_OK) {
63     absl::FPrintF(stderr, "%s\n", TF_Message(status));
64     TF_DeleteStatus(status);
65     return false;
66   }
67   tensor->reset(new TFProfTensor(std::move(out_tensor)));
68   TF_DeleteStatus(status);
69   return true;
70 }
71 
ShouldShow(const ShowNode * node,const Options & opts,int depth) const72 bool TFShow::ShouldShow(const ShowNode* node, const Options& opts,
73                         int depth) const {
74   // Always show kTFProfRoot.
75   if (node->name() == kTFProfRoot) return true;
76 
77   if (node->proto().total_requested_bytes() < opts.min_bytes ||
78       node->proto().total_peak_bytes() < opts.min_peak_bytes ||
79       node->proto().total_residual_bytes() < opts.min_residual_bytes ||
80       node->proto().total_output_bytes() < opts.min_output_bytes ||
81       node->proto().total_exec_micros() < opts.min_micros ||
82       node->proto().total_accelerator_exec_micros() <
83           opts.min_accelerator_micros ||
84       node->proto().total_cpu_exec_micros() < opts.min_cpu_micros ||
85       node->proto().parameters() < opts.min_params ||
86       node->proto().float_ops() < opts.min_float_ops ||
87       node->proto().run_count() < opts.min_occurrence ||
88       depth > opts.max_depth || !ShouldShowIfExtra(node, opts, depth)) {
89     return false;
90   }
91 
92   bool show = false;
93   if (opts.show_name_regexes.size() == 1 && opts.show_name_regexes[0] == ".*") {
94     show = true;
95   } else {
96     for (const string& regex : opts.show_name_regexes) {
97       if (RE2::FullMatch(node->name(), regex)) {
98         show = true;
99         break;
100       }
101     }
102   }
103   // Don't show if show_name_regexes don't cover it.
104   if (!show) return false;
105   // Don't show if hide_name_regexes cover it.
106   for (const string& regex : opts.hide_name_regexes) {
107     if (RE2::FullMatch(node->name(), regex)) return false;
108   }
109   return true;
110 }
111 
ShouldTrim(const ShowNode * node,const std::vector<string> & regexes) const112 bool TFShow::ShouldTrim(const ShowNode* node,
113                         const std::vector<string>& regexes) const {
114   for (const string& regex : regexes) {
115     if (RE2::FullMatch(node->name(), regex)) {
116       return true;
117     }
118   }
119   return false;
120 }
121 
ReAccount(ShowNode * node,const Options & opts)122 bool TFShow::ReAccount(ShowNode* node, const Options& opts) {
123   node->ReInit(opts.step);
124   if (opts.account_type_regexes.size() == 1 &&
125       opts.account_type_regexes[0] == ".*") {
126     return true;
127   }
128   for (const string& regex : opts.account_type_regexes) {
129     for (const string& type : node->node->op_types()) {
130       if (RE2::FullMatch(type, regex)) {
131         return true;
132       }
133     }
134   }
135   return false;
136 }
137 
FormatNodeMemory(ShowNode * node,int64_t bytes,int64_t total_bytes) const138 string TFShow::FormatNodeMemory(ShowNode* node, int64_t bytes,
139                                 int64_t total_bytes) const {
140   string memory = FormatMemory(total_bytes);
141   if (node->account) {
142     memory = FormatMemory(bytes) + "/" + memory;
143   } else {
144     memory = "--/" + memory;
145   }
146   return memory;
147 }
148 
FormatNode(ShowNode * node,const Options & opts) const149 string TFShow::FormatNode(ShowNode* node, const Options& opts) const {
150   std::vector<string> info;
151   if (opts.select.find(kShown[2]) != opts.select.end()) {
152     const string shape = FormatShapes(node->node->shape());
153     if (!shape.empty()) {
154       info.push_back(shape);
155     }
156     string params = FormatNumber(node->proto().total_parameters()) + " params";
157     if (node->account) {
158       params = FormatNumber(node->proto().parameters()) + "/" + params;
159     } else {
160       params = "--/" + params;
161     }
162     info.push_back(params);
163   }
164   if (opts.select.find(kShown[3]) != opts.select.end()) {
165     string fops = FormatNumber(node->proto().total_float_ops()) + " flops";
166     if (node->account) {
167       fops = FormatNumber(node->proto().float_ops()) + "/" + fops;
168     } else {
169       fops = "--/" + fops;
170     }
171     info.push_back(fops);
172   }
173   if (opts.select.find(kShown[0]) != opts.select.end()) {
174     info.push_back(FormatNodeMemory(node, node->proto().requested_bytes(),
175                                     node->proto().total_requested_bytes()));
176   }
177   if (opts.select.find(kShown[11]) != opts.select.end()) {
178     info.push_back(FormatNodeMemory(node, node->proto().peak_bytes(),
179                                     node->proto().total_peak_bytes()));
180   }
181   if (opts.select.find(kShown[12]) != opts.select.end()) {
182     info.push_back(FormatNodeMemory(node, node->proto().residual_bytes(),
183                                     node->proto().total_residual_bytes()));
184   }
185   if (opts.select.find(kShown[13]) != opts.select.end()) {
186     info.push_back(FormatNodeMemory(node, node->proto().output_bytes(),
187                                     node->proto().total_output_bytes()));
188   }
189   if (opts.select.find(kShown[1]) != opts.select.end()) {
190     info.push_back(FormatTotalExecTime(node, opts));
191     info.push_back(FormatAcceleratorExecTime(node, opts));
192     info.push_back(FormatCPUExecTime(node, opts));
193   }
194   if (opts.select.find(kShown[9]) != opts.select.end() &&
195       opts.select.find(kShown[1]) == opts.select.end()) {
196     info.push_back(FormatAcceleratorExecTime(node, opts));
197   }
198   if (opts.select.find(kShown[10]) != opts.select.end() &&
199       opts.select.find(kShown[1]) == opts.select.end()) {
200     info.push_back(FormatCPUExecTime(node, opts));
201   }
202   if (opts.select.find(kShown[5]) != opts.select.end()) {
203     if (node->proto().devices_size() > 0) {
204       info.push_back(absl::StrJoin(node->proto().devices(), "|"));
205     }
206   }
207   if (opts.select.find(kShown[6]) != opts.select.end()) {
208     const std::set<string>& op_types = node->node->op_types();
209     info.push_back(absl::StrJoin(op_types, "|"));
210   }
211   if (opts.select.find(kShown[7]) != opts.select.end()) {
212     string run = FormatNumber(node->proto().total_run_count());
213     if (node->account) {
214       run = FormatNumber(node->proto().run_count()) + "/" + run;
215     } else {
216       run = "--/" + run;
217     }
218     string definition = FormatNumber(node->proto().total_definition_count());
219     if (node->account) {
220       definition = "1/" + definition;
221     } else {
222       definition = "--/" + definition;
223     }
224     info.push_back(run + "|" + definition);
225   }
226   if (opts.select.find(kShown[8]) != opts.select.end()) {
227     std::vector<string> shape_vec;
228     for (const auto& s : node->node->input_shapes()) {
229       if (s.second.empty()) {
230         shape_vec.push_back(absl::StrFormat("%d:unknown", s.first));
231       } else {
232         shape_vec.push_back(
233             absl::StrFormat("%d:%s", s.first, absl::StrJoin(s.second, "x")));
234       }
235     }
236     info.push_back(absl::StrJoin(shape_vec, "|"));
237   }
238 
239   return absl::StrFormat("%s (%s)", node->name(), absl::StrJoin(info, ", "));
240 }
241 
FormatLegend(const Options & opts) const242 string TFShow::FormatLegend(const Options& opts) const {
243   std::vector<string> legends;
244   if (opts.select.find(kShown[2]) != opts.select.end()) {
245     legends.push_back("# parameters");
246   }
247   if (opts.select.find(kShown[3]) != opts.select.end()) {
248     legends.push_back("# float_ops");
249   }
250   if (opts.select.find(kShown[0]) != opts.select.end()) {
251     legends.push_back("requested bytes");
252   }
253   if (opts.select.find(kShown[11]) != opts.select.end()) {
254     legends.push_back("peak bytes");
255   }
256   if (opts.select.find(kShown[12]) != opts.select.end()) {
257     legends.push_back("residual bytes");
258   }
259   if (opts.select.find(kShown[13]) != opts.select.end()) {
260     legends.push_back("output bytes");
261   }
262   if (opts.select.find(kShown[1]) != opts.select.end()) {
263     legends.push_back("total execution time");
264     legends.push_back("accelerator execution time");
265     legends.push_back("cpu execution time");
266   }
267   if (opts.select.find(kShown[9]) != opts.select.end() &&
268       opts.select.find(kShown[1]) == opts.select.end()) {
269     legends.push_back("accelerator execution time");
270   }
271   if (opts.select.find(kShown[10]) != opts.select.end() &&
272       opts.select.find(kShown[1]) == opts.select.end()) {
273     legends.push_back("cpu execution time");
274   }
275   if (opts.select.find(kShown[5]) != opts.select.end()) {
276     legends.push_back("assigned devices");
277   }
278   if (opts.select.find(kShown[6]) != opts.select.end()) {
279     legends.push_back("op types");
280   }
281   if (opts.select.find(kShown[7]) != opts.select.end()) {
282     legends.push_back("op count (run|defined)");
283   }
284   if (opts.select.find(kShown[8]) != opts.select.end()) {
285     legends.push_back("input shapes");
286   }
287   return absl::StrFormat("node name | %s\n", absl::StrJoin(legends, " | "));
288 }
289 
290 }  // namespace tfprof
291 }  // namespace tensorflow
292