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