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