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