• 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/tfprof_options.h"
17 
18 #include "absl/strings/str_format.h"
19 #include "absl/strings/str_split.h"
20 #include "tensorflow/core/lib/core/errors.h"
21 #include "tensorflow/core/profiler/tfprof_options.pb.h"
22 
23 namespace tensorflow {
24 namespace tfprof {
25 namespace {
KeyValueToStr(const std::map<string,string> & kv_map)26 string KeyValueToStr(const std::map<string, string>& kv_map) {
27   std::vector<string> kv_vec;
28   kv_vec.reserve(kv_map.size());
29   for (const auto& pair : kv_map) {
30     kv_vec.push_back(absl::StrCat(pair.first, "=", pair.second));
31   }
32   return absl::StrJoin(kv_vec, ",");
33 }
34 }  // namespace
35 
ParseOutput(const string & output_opt,string * output_type,std::map<string,string> * output_options)36 tensorflow::Status ParseOutput(const string& output_opt, string* output_type,
37                                std::map<string, string>* output_options) {
38   // The default is to use stdout.
39   if (output_opt.empty()) {
40     *output_type = kOutput[1];
41     return tensorflow::Status::OK();
42   }
43 
44   std::set<string> output_types(kOutput,
45                                 kOutput + sizeof(kOutput) / sizeof(*kOutput));
46   auto opt_split = output_opt.find(':');
47   std::vector<string> kv_split;
48   if (opt_split == output_opt.npos) {
49     if (output_types.find(output_opt) == output_types.end()) {
50       return tensorflow::Status(
51           tensorflow::error::INVALID_ARGUMENT,
52           absl::StrFormat("E.g. Unknown output type: %s, Valid types: %s\n",
53                           output_opt, absl::StrJoin(output_types, ",")));
54     }
55     *output_type = output_opt;
56   } else {
57     *output_type = output_opt.substr(0, opt_split);
58     if (output_types.find(*output_type) == output_types.end()) {
59       return tensorflow::Status(
60           tensorflow::error::INVALID_ARGUMENT,
61           absl::StrFormat("E.g. Unknown output type: %s, Valid types: %s\n",
62                           *output_type, absl::StrJoin(output_types, ",")));
63     }
64     kv_split = absl::StrSplit(output_opt.substr(opt_split + 1), ",",
65                               absl::SkipEmpty());
66   }
67 
68   std::set<string> valid_options;
69   std::set<string> required_options;
70   if (*output_type == kOutput[0]) {
71     valid_options.insert(
72         kTimelineOpts,
73         kTimelineOpts + sizeof(kTimelineOpts) / sizeof(*kTimelineOpts));
74     required_options.insert(
75         kTimelineRequiredOpts,
76         kTimelineRequiredOpts +
77             sizeof(kTimelineRequiredOpts) / sizeof(*kTimelineRequiredOpts));
78   } else if (*output_type == kOutput[2]) {
79     valid_options.insert(kFileOpts,
80                          kFileOpts + sizeof(kFileOpts) / sizeof(*kFileOpts));
81     required_options.insert(kFileRequiredOpts,
82                             kFileRequiredOpts + sizeof(kFileRequiredOpts) /
83                                                     sizeof(*kFileRequiredOpts));
84   } else if (*output_type == kOutput[3]) {
85     valid_options.insert(kPprofOpts,
86                          kPprofOpts + sizeof(kPprofOpts) / sizeof(*kPprofOpts));
87     required_options.insert(
88         kPprofRequiredOpts,
89         kPprofRequiredOpts +
90             sizeof(kPprofRequiredOpts) / sizeof(*kPprofRequiredOpts));
91   }
92 
93   for (const string& kv_str : kv_split) {
94     const std::vector<string> kv =
95         absl::StrSplit(kv_str, "=", absl::SkipEmpty());
96     if (kv.size() < 2) {
97       return tensorflow::Status(
98           tensorflow::error::INVALID_ARGUMENT,
99           "Visualize format: -output timeline:key=value,key=value,...");
100     }
101     if (valid_options.find(kv[0]) == valid_options.end()) {
102       return tensorflow::Status(
103           tensorflow::error::INVALID_ARGUMENT,
104           absl::StrFormat("Unrecognized options %s for output_type: %s\n",
105                           kv[0], *output_type));
106     }
107     const std::vector<string> kv_without_key(kv.begin() + 1, kv.end());
108     (*output_options)[kv[0]] = absl::StrJoin(kv_without_key, "=");
109   }
110 
111   for (const string& opt : required_options) {
112     if (output_options->find(opt) == output_options->end()) {
113       return tensorflow::Status(
114           tensorflow::error::INVALID_ARGUMENT,
115           absl::StrFormat("Missing required output_options for %s\n"
116                           "E.g. -output %s:%s=...\n",
117                           *output_type, *output_type, opt));
118     }
119   }
120   return tensorflow::Status::OK();
121 }
122 
FromProtoStr(const string & opts_proto_str,Options * opts)123 tensorflow::Status Options::FromProtoStr(const string& opts_proto_str,
124                                          Options* opts) {
125   OptionsProto opts_pb;
126   if (!opts_pb.ParseFromString(opts_proto_str)) {
127     return tensorflow::Status(
128         tensorflow::error::INTERNAL,
129         absl::StrCat("Failed to parse option string from Python API: ",
130                      opts_proto_str));
131   }
132 
133   string output_type;
134   std::map<string, string> output_options;
135   tensorflow::Status s =
136       ParseOutput(opts_pb.output(), &output_type, &output_options);
137   if (!s.ok()) return s;
138 
139   if (!opts_pb.dump_to_file().empty()) {
140     absl::FPrintF(stderr,
141                   "-dump_to_file option is deprecated. "
142                   "Please use -output file:outfile=<filename>\n");
143     absl::FPrintF(stderr,
144                   "-output %s is overwritten with -output file:outfile=%s\n",
145                   opts_pb.output(), opts_pb.dump_to_file());
146     output_type = kOutput[2];
147     output_options.clear();
148     output_options[kFileOpts[0]] = opts_pb.dump_to_file();
149   }
150 
151   *opts = Options(
152       opts_pb.max_depth(), opts_pb.min_bytes(), opts_pb.min_peak_bytes(),
153       opts_pb.min_residual_bytes(), opts_pb.min_output_bytes(),
154       opts_pb.min_micros(), opts_pb.min_accelerator_micros(),
155       opts_pb.min_cpu_micros(), opts_pb.min_params(), opts_pb.min_float_ops(),
156       opts_pb.min_occurrence(), opts_pb.step(), opts_pb.order_by(),
157       std::vector<string>(opts_pb.account_type_regexes().begin(),
158                           opts_pb.account_type_regexes().end()),
159       std::vector<string>(opts_pb.start_name_regexes().begin(),
160                           opts_pb.start_name_regexes().end()),
161       std::vector<string>(opts_pb.trim_name_regexes().begin(),
162                           opts_pb.trim_name_regexes().end()),
163       std::vector<string>(opts_pb.show_name_regexes().begin(),
164                           opts_pb.show_name_regexes().end()),
165       std::vector<string>(opts_pb.hide_name_regexes().begin(),
166                           opts_pb.hide_name_regexes().end()),
167       opts_pb.account_displayed_op_only(),
168       std::vector<string>(opts_pb.select().begin(), opts_pb.select().end()),
169       output_type, output_options);
170   return tensorflow::Status::OK();
171 }
172 
ToString() const173 std::string Options::ToString() const {
174   // clang-format off
175   const std::string s = absl::StrFormat(
176       "%-28s%d\n"
177       "%-28s%d\n"
178       "%-28s%d\n"
179       "%-28s%d\n"
180       "%-28s%d\n"
181       "%-28s%d\n"
182       "%-28s%d\n"
183       "%-28s%d\n"
184       "%-28s%d\n"
185       "%-28s%d\n"
186       "%-28s%d\n"
187       "%-28s%d\n"
188       "%-28s%s\n"
189       "%-28s%s\n"
190       "%-28s%s\n"
191       "%-28s%s\n"
192       "%-28s%s\n"
193       "%-28s%s\n"
194       "%-28s%s\n"
195       "%-28s%s\n"
196       "%-28s%s:%s\n",
197       kOptions[0],  max_depth,
198       kOptions[1],  min_bytes,
199       kOptions[2],  min_peak_bytes,
200       kOptions[3],  min_residual_bytes,
201       kOptions[4],  min_output_bytes,
202       kOptions[5],  min_micros,
203       kOptions[6],  min_accelerator_micros,
204       kOptions[7],  min_cpu_micros,
205       kOptions[8],  min_params,
206       kOptions[9],  min_float_ops,
207       kOptions[10], min_occurrence,
208       kOptions[11], step,
209       kOptions[12], order_by,
210       kOptions[13], absl::StrJoin(account_type_regexes, ","),
211       kOptions[14], absl::StrJoin(start_name_regexes, ","),
212       kOptions[15], absl::StrJoin(trim_name_regexes, ","),
213       kOptions[16], absl::StrJoin(show_name_regexes, ","),
214       kOptions[17], absl::StrJoin(hide_name_regexes, ","),
215       kOptions[18], (account_displayed_op_only ? "true" : "false"),
216       kOptions[19], absl::StrJoin(select, ","),
217       kOptions[20], output_type, KeyValueToStr(output_options));
218   // clang-format on
219   return s;
220 }
221 
222 }  // namespace tfprof
223 }  // namespace tensorflow
224