• 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     const std::vector<string> kv_without_key(kv.begin() + 1, kv.end());
111     (*output_options)[kv[0]] = str_util::Join(kv_without_key, "=");
112   }
113 
114   for (const string& opt : required_options) {
115     if (output_options->find(opt) == output_options->end()) {
116       return tensorflow::Status(
117           tensorflow::error::INVALID_ARGUMENT,
118           strings::Printf("Missing required output_options for %s\n"
119                           "E.g. -output %s:%s=...\n",
120                           output_type->c_str(), output_type->c_str(),
121                           opt.c_str()));
122     }
123   }
124   return tensorflow::Status::OK();
125 }
126 
FromProtoStr(const string & opts_proto_str,Options * opts)127 tensorflow::Status Options::FromProtoStr(const string& opts_proto_str,
128                                          Options* opts) {
129   OptionsProto opts_pb;
130   if (!opts_pb.ParseFromString(opts_proto_str)) {
131     return tensorflow::Status(
132         tensorflow::error::INTERNAL,
133         strings::StrCat("Failed to parse option string from Python API: ",
134                         opts_proto_str));
135   }
136 
137   string output_type;
138   std::map<string, string> output_options;
139   tensorflow::Status s =
140       ParseOutput(opts_pb.output(), &output_type, &output_options);
141   if (!s.ok()) return s;
142 
143   if (!opts_pb.dump_to_file().empty()) {
144     fprintf(stderr,
145             "-dump_to_file option is deprecated. "
146             "Please use -output file:outfile=<filename>\n");
147     fprintf(stderr, "-output %s is overwritten with -output file:outfile=%s\n",
148             opts_pb.output().c_str(), opts_pb.dump_to_file().c_str());
149     output_type = kOutput[2];
150     output_options.clear();
151     output_options[kFileOpts[0]] = opts_pb.dump_to_file();
152   }
153 
154   *opts = Options(
155       opts_pb.max_depth(), opts_pb.min_bytes(), opts_pb.min_peak_bytes(),
156       opts_pb.min_residual_bytes(), opts_pb.min_output_bytes(),
157       opts_pb.min_micros(), opts_pb.min_accelerator_micros(),
158       opts_pb.min_cpu_micros(), opts_pb.min_params(), opts_pb.min_float_ops(),
159       opts_pb.min_occurrence(), opts_pb.step(), opts_pb.order_by(),
160       std::vector<string>(opts_pb.account_type_regexes().begin(),
161                           opts_pb.account_type_regexes().end()),
162       std::vector<string>(opts_pb.start_name_regexes().begin(),
163                           opts_pb.start_name_regexes().end()),
164       std::vector<string>(opts_pb.trim_name_regexes().begin(),
165                           opts_pb.trim_name_regexes().end()),
166       std::vector<string>(opts_pb.show_name_regexes().begin(),
167                           opts_pb.show_name_regexes().end()),
168       std::vector<string>(opts_pb.hide_name_regexes().begin(),
169                           opts_pb.hide_name_regexes().end()),
170       opts_pb.account_displayed_op_only(),
171       std::vector<string>(opts_pb.select().begin(), opts_pb.select().end()),
172       output_type, output_options);
173   return tensorflow::Status::OK();
174 }
175 
ToString() const176 string Options::ToString() const {
177   const string s = strings::Printf(
178       "%-28s%d\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%lld\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\n"
198       "%-28s%s:%s\n",
199       kOptions[0], max_depth, kOptions[1], min_bytes, kOptions[2],
200       min_peak_bytes, kOptions[3], min_residual_bytes, kOptions[4],
201       min_output_bytes, kOptions[5], min_micros, kOptions[6],
202       min_accelerator_micros, kOptions[7], min_cpu_micros, kOptions[8],
203       min_params, kOptions[9], min_float_ops, kOptions[10], min_occurrence,
204       kOptions[11], step, kOptions[12], order_by.c_str(), kOptions[13],
205       str_util::Join(account_type_regexes, ",").c_str(), kOptions[14],
206       str_util::Join(start_name_regexes, ",").c_str(), kOptions[15],
207       str_util::Join(trim_name_regexes, ",").c_str(), kOptions[16],
208       str_util::Join(show_name_regexes, ",").c_str(), kOptions[17],
209       str_util::Join(hide_name_regexes, ",").c_str(), kOptions[18],
210       (account_displayed_op_only ? "true" : "false"), kOptions[19],
211       str_util::Join(select, ",").c_str(), kOptions[20], output_type.c_str(),
212       KeyValueToStr(output_options).c_str());
213   return s;
214 }
215 
216 }  // namespace tfprof
217 }  // namespace tensorflow
218