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/internal/print_model_analysis.h"
17
18 #include <stdio.h>
19
20 #include <memory>
21 #include <utility>
22
23 #include "absl/strings/str_format.h"
24 #include "tensorflow/core/profiler/internal/advisor/tfprof_advisor.h"
25 #include "tensorflow/core/profiler/internal/tfprof_stats.h"
26 #include "tensorflow/core/profiler/tfprof_log.pb.h"
27 #include "tensorflow/core/profiler/tfprof_options.h"
28 #include "tensorflow/core/profiler/tfprof_options.pb.h"
29 #include "tensorflow/core/profiler/tfprof_output.pb.h"
30
31 namespace tensorflow {
32 namespace tfprof {
33 namespace {
34 TFStats* tf_stat = nullptr;
35
RunProfile(const string & command,const string & options,TFStats * tf_stats)36 string RunProfile(const string& command, const string& options,
37 TFStats* tf_stats) {
38 if (command == kCmds[4]) {
39 AdvisorOptionsProto option_pb;
40 if (!option_pb.ParseFromString(options)) {
41 absl::FPrintF(stderr, "Cannot parse AdvisorOptionsProto\n");
42 return "";
43 }
44 tf_stats->BuildAllViews();
45 return Advisor(tf_stats).Advise(option_pb).SerializeAsString();
46 } else {
47 tf_stats->BuildView(command);
48 }
49
50 Options opts;
51 tensorflow::Status s = Options::FromProtoStr(options, &opts);
52 if (!s.ok()) {
53 absl::FPrintF(stderr, "%s\n", s.ToString());
54 return "";
55 }
56
57 if (opts.output_type == kOutput[1]) {
58 absl::PrintF(
59 "\n=========================Options=============================\n");
60 absl::PrintF("%s", opts.ToString());
61 absl::PrintF(
62 "\n==================Model Analysis Report======================\n");
63 string ret = "";
64 if (command == kCmds[2] || command == kCmds[3]) {
65 ret = tf_stats->ShowMultiGraphNode(command, opts).SerializeAsString();
66 } else if (command == kCmds[0] || command == kCmds[1]) {
67 ret = tf_stats->ShowGraphNode(command, opts).SerializeAsString();
68 } else {
69 absl::FPrintF(stderr, "Unknown command: %s\n", command);
70 }
71 absl::PrintF(
72 "\n======================End of Report==========================\n");
73 fflush(stdout);
74 return ret;
75 }
76 if (command == kCmds[2] || command == kCmds[3]) {
77 return tf_stats->ShowMultiGraphNode(command, opts).SerializeAsString();
78 } else if (command == kCmds[0] || command == kCmds[1]) {
79 return tf_stats->ShowGraphNode(command, opts).SerializeAsString();
80 } else {
81 absl::FPrintF(stderr, "Unknown command: %s\n", command);
82 return "";
83 }
84 }
85 } // namespace
86
NewProfiler(const string * graph,const string * op_log)87 bool NewProfiler(const string* graph, const string* op_log) {
88 std::unique_ptr<GraphDef> graph_ptr(new GraphDef());
89 if (graph && !graph->empty()) {
90 if (!graph_ptr->ParseFromString(*graph)) {
91 if (!protobuf::TextFormat::ParseFromString(*graph, graph_ptr.get())) {
92 absl::FPrintF(stderr, "Failed to parse graph\n");
93 return false;
94 }
95 }
96 }
97
98 std::unique_ptr<OpLogProto> op_log_ptr;
99 if (op_log && !op_log->empty()) {
100 op_log_ptr.reset(new OpLogProto());
101 if (!op_log_ptr->ParseFromString(*op_log)) {
102 absl::FPrintF(stderr, "Failed to parse OpLogProto.\n");
103 return false;
104 }
105 }
106 tf_stat = new TFStats(std::move(graph_ptr), nullptr, std::move(op_log_ptr),
107 nullptr);
108 return true;
109 }
110
ProfilerFromFile(const string * filename)111 void ProfilerFromFile(const string* filename) {
112 CHECK(!tf_stat) << "Currently only 1 living tfprof profiler is allowed";
113 CHECK(filename) << "Missing profile filename to init profiler from file";
114 tf_stat = new TFStats(*filename, nullptr);
115 }
116
DeleteProfiler()117 void DeleteProfiler() {
118 if (tf_stat) {
119 delete tf_stat;
120 tf_stat = nullptr;
121 }
122 }
123
AddStep(int64_t step,const string * graph,const string * run_meta,const string * op_log)124 double AddStep(int64_t step, const string* graph, const string* run_meta,
125 const string* op_log) {
126 CHECK(tf_stat);
127
128 if (graph && !graph->empty()) {
129 std::unique_ptr<GraphDef> graph_ptr(new GraphDef());
130 if (!graph_ptr->ParseFromString(*graph)) {
131 if (!protobuf::TextFormat::ParseFromString(*graph, graph_ptr.get())) {
132 absl::FPrintF(stderr, "Failed to parse graph\n");
133 }
134 }
135 tf_stat->AddGraph(std::move(graph_ptr));
136 }
137
138 CHECK(run_meta && !run_meta->empty());
139 // TODO(xpan): Better error handling.
140 std::unique_ptr<RunMetadata> run_meta_ptr(new RunMetadata());
141 run_meta_ptr->ParseFromString(*run_meta);
142 tf_stat->AddRunMeta(step, std::move(run_meta_ptr));
143
144 if (op_log && !op_log->empty()) {
145 std::unique_ptr<OpLogProto> op_log_ptr;
146 op_log_ptr.reset(new OpLogProto());
147 op_log_ptr->ParseFromString(*op_log);
148 tf_stat->AddOpLogProto(std::move(op_log_ptr));
149 }
150 return tf_stat->run_coverage();
151 }
152
Profile(const string * command,const string * options)153 string Profile(const string* command, const string* options) {
154 CHECK(tf_stat);
155 CHECK(command) << "command mustn't be null";
156 CHECK(options) << "options mustn't be null";
157 return RunProfile(*command, *options, tf_stat);
158 }
159
SerializeToString()160 string SerializeToString() {
161 CHECK(tf_stat);
162 string content;
163 tf_stat->SerializeToString(&content);
164 return content;
165 }
166
WriteProfile(const string * filename)167 void WriteProfile(const string* filename) {
168 CHECK(tf_stat);
169 CHECK(filename) << "empty file name when asking to write profile.";
170 tf_stat->WriteProfile(*filename);
171 }
172
PrintModelAnalysis(const string * graph,const string * run_meta,const string * op_log,const string * command,const string * options)173 string PrintModelAnalysis(const string* graph, const string* run_meta,
174 const string* op_log, const string* command,
175 const string* options) {
176 CHECK(command) << "command mustn't be null";
177 CHECK(options) << "options mustn't be null";
178 std::unique_ptr<GraphDef> graph_ptr(new GraphDef());
179 if (graph && !graph->empty()) {
180 graph_ptr->ParseFromString(*graph);
181 }
182
183 std::unique_ptr<RunMetadata> run_meta_ptr;
184 if (run_meta && !run_meta->empty()) {
185 run_meta_ptr.reset(new RunMetadata());
186 run_meta_ptr->ParseFromString(*run_meta);
187 }
188
189 std::unique_ptr<OpLogProto> op_log_ptr;
190 if (op_log && !op_log->empty()) {
191 op_log_ptr.reset(new OpLogProto());
192 op_log_ptr->ParseFromString(*op_log);
193 }
194
195 // TODO(xpan): Maybe need to init the checkpoint reader?
196 std::unique_ptr<checkpoint::CheckpointReader> ckpt_reader;
197
198 TFStats tf_stats(std::move(graph_ptr), std::move(run_meta_ptr),
199 std::move(op_log_ptr), std::move(ckpt_reader));
200
201 return RunProfile(*command, *options, &tf_stats);
202 }
203
204 } // namespace tfprof
205 } // namespace tensorflow
206