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