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