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