1 /* Copyright 2020 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/convert/xplane_to_tools_data.h"
17
18 #include <utility>
19 #include <vector>
20
21 #include "tensorflow/core/platform/env.h"
22 #include "tensorflow/core/platform/logging.h"
23 #include "tensorflow/core/platform/protobuf.h"
24 #include "tensorflow/core/profiler/convert/op_stats_to_input_pipeline_analysis.h"
25 #include "tensorflow/core/profiler/convert/op_stats_to_overview_page.h"
26 #include "tensorflow/core/profiler/convert/op_stats_to_pod_viewer.h"
27 #include "tensorflow/core/profiler/convert/op_stats_to_tf_stats.h"
28 #include "tensorflow/core/profiler/convert/xplane_to_memory_profile.h"
29 #include "tensorflow/core/profiler/convert/xplane_to_op_stats.h"
30 #include "tensorflow/core/profiler/convert/xplane_to_tf_data_stats.h"
31 #include "tensorflow/core/profiler/convert/xplane_to_trace_events.h"
32 #include "tensorflow/core/profiler/protobuf/input_pipeline.pb.h"
33 #include "tensorflow/core/profiler/protobuf/kernel_stats.pb.h"
34 #include "tensorflow/core/profiler/protobuf/op_stats.pb.h"
35 #include "tensorflow/core/profiler/protobuf/overview_page.pb.h"
36 #include "tensorflow/core/profiler/protobuf/pod_viewer.pb.h"
37 #include "tensorflow/core/profiler/protobuf/tf_data_stats.pb.h"
38 #include "tensorflow/core/profiler/protobuf/tf_stats.pb.h"
39 #include "tensorflow/core/profiler/protobuf/xplane.pb.h"
40 #include "tensorflow/core/profiler/utils/xplane_schema.h"
41 #include "tensorflow/core/profiler/utils/xplane_utils.h"
42
43 namespace tensorflow {
44 namespace profiler {
45
46 namespace {
47
ConvertXSpaceToTraceEvents(const std::vector<std::string> & xspace_paths)48 std::pair<std::string, bool> ConvertXSpaceToTraceEvents(
49 const std::vector<std::string>& xspace_paths) {
50 if (xspace_paths.size() != 1) {
51 LOG(WARNING) << "Trace events tool expects only 1 XSpace path but gets "
52 << xspace_paths.size();
53 return std::make_pair("", false);
54 }
55
56 XSpace xspace;
57 Status status = ReadBinaryProto(Env::Default(), xspace_paths[0], &xspace);
58 if (!status.ok()) {
59 LOG(WARNING) << "Could not read XSpace for trace events: "
60 << xspace_paths[0];
61 return std::make_pair("", false);
62 }
63 std::string content;
64 ConvertXSpaceToTraceEventsString(xspace, &content);
65 return std::make_pair(content, true);
66 }
67
ConvertMultiXSpacesToOverviewPage(const std::vector<std::string> & xspace_paths)68 std::pair<std::string, bool> ConvertMultiXSpacesToOverviewPage(
69 const std::vector<std::string>& xspace_paths) {
70 OpStatsOptions options;
71 options.generate_kernel_stats_db = true;
72 options.generate_op_metrics_db = true;
73 options.generate_step_db = true;
74 OpStats combined_op_stats;
75 Status status = ConvertMultiXSpacesToCombinedOpStats(xspace_paths, options,
76 &combined_op_stats);
77 if (!status.ok()) {
78 LOG(WARNING) << "Could not generate OpStats for overview page. Error: "
79 << status.error_message();
80 return std::make_pair("", false);
81 }
82 // TODO(profiler): xspace should tell whether this is sampling mode.
83 return std::make_pair(
84 ConvertOpStatsToOverviewPage(combined_op_stats).SerializeAsString(),
85 true);
86 }
87
ConvertMultiXSpacesToInputPipeline(const std::vector<std::string> & xspace_paths)88 std::pair<std::string, bool> ConvertMultiXSpacesToInputPipeline(
89 const std::vector<std::string>& xspace_paths) {
90 OpStatsOptions options;
91 options.generate_op_metrics_db = true;
92 options.generate_step_db = true;
93 OpStats combined_op_stats;
94 Status status = ConvertMultiXSpacesToCombinedOpStats(xspace_paths, options,
95 &combined_op_stats);
96 if (!status.ok()) {
97 LOG(WARNING) << "Could not generate OpStats for input pipeline. Error: "
98 << status.error_message();
99 return std::make_pair("", false);
100 }
101 return std::make_pair(ConvertOpStatsToInputPipelineAnalysis(combined_op_stats)
102 .SerializeAsString(),
103 true);
104 }
105
ConvertMultiXSpacesToTfStats(const std::vector<std::string> & xspace_paths)106 std::pair<std::string, bool> ConvertMultiXSpacesToTfStats(
107 const std::vector<std::string>& xspace_paths) {
108 OpStatsOptions options;
109 options.generate_op_metrics_db = true;
110 options.generate_kernel_stats_db = true;
111 OpStats combined_op_stats;
112 Status status = ConvertMultiXSpacesToCombinedOpStats(xspace_paths, options,
113 &combined_op_stats);
114 if (!status.ok()) {
115 LOG(WARNING) << "Could not generate OpStats for tensorflow stats. Error: "
116 << status.error_message();
117 return std::make_pair("", false);
118 }
119 return std::make_pair(
120 ConvertOpStatsToTfStats(combined_op_stats).SerializeAsString(), true);
121 }
122
ConvertMultiXSpacesToKernelStats(const std::vector<std::string> & xspace_paths)123 std::pair<std::string, bool> ConvertMultiXSpacesToKernelStats(
124 const std::vector<std::string>& xspace_paths) {
125 OpStatsOptions options;
126 options.generate_kernel_stats_db = true;
127 OpStats combined_op_stats;
128 Status status = ConvertMultiXSpacesToCombinedOpStats(xspace_paths, options,
129 &combined_op_stats);
130 if (!status.ok()) {
131 LOG(WARNING) << "Could not generate OpStats for kernel stats. Error: "
132 << status.error_message();
133 return std::make_pair("", false);
134 }
135 return std::make_pair(combined_op_stats.kernel_stats_db().SerializeAsString(),
136 true);
137 }
138
ConvertXSpaceToMemoryProfile(const std::vector<std::string> & xspace_paths)139 std::pair<std::string, bool> ConvertXSpaceToMemoryProfile(
140 const std::vector<std::string>& xspace_paths) {
141 if (xspace_paths.size() != 1) {
142 LOG(WARNING) << "Memory profile tool expects only 1 XSpace path but gets "
143 << xspace_paths.size();
144 return std::make_pair("", false);
145 }
146 XSpace xspace;
147 Status status = ReadBinaryProto(Env::Default(), xspace_paths[0], &xspace);
148 if (!status.ok()) {
149 LOG(WARNING) << "Could not read XSpace for memory profile: "
150 << xspace_paths[0];
151 return std::make_pair("", false);
152 }
153 std::string json_output;
154 status = ConvertXSpaceToMemoryProfileJson(xspace, &json_output);
155 if (!status.ok()) {
156 LOG(WARNING) << "Could not generate memory profile. Error: "
157 << status.error_message();
158 return std::make_pair("", false);
159 }
160 return std::make_pair(json_output, true);
161 }
162
ConvertMultiXSpacesToPodViewer(const std::vector<std::string> & xspace_paths)163 std::pair<std::string, bool> ConvertMultiXSpacesToPodViewer(
164 const std::vector<std::string>& xspace_paths) {
165 OpStatsOptions options;
166 options.generate_op_metrics_db = true;
167 options.generate_step_db = true;
168 OpStats combined_op_stats;
169 Status status = ConvertMultiXSpacesToCombinedOpStats(xspace_paths, options,
170 &combined_op_stats);
171 if (!status.ok()) {
172 LOG(WARNING) << "Could not generate OpStats for pod_viewer. Error: "
173 << status.error_message();
174 return std::make_pair("", false);
175 }
176
177 std::string json_output;
178 protobuf::util::JsonPrintOptions opts;
179 opts.always_print_primitive_fields = true;
180 auto encode_status = protobuf::util::MessageToJsonString(
181 ConvertOpStatsToPodViewer(combined_op_stats), &json_output, opts);
182 if (!encode_status.ok()) {
183 LOG(WARNING) << "Could not convert pod viewer proto to json. Error: "
184 << encode_status.message();
185 return std::make_pair("", false);
186 }
187 return std::make_pair(json_output, true);
188 }
189
ConvertMultiXSpacesToTfDataBottleneckAnalysis(const std::vector<std::string> & xspace_paths)190 std::pair<std::string, bool> ConvertMultiXSpacesToTfDataBottleneckAnalysis(
191 const std::vector<std::string>& xspace_paths) {
192 CombinedTfDataStats combined_tf_data_stats;
193 CombinedTfDataStatsBuilder builder(&combined_tf_data_stats);
194 for (const std::string& xspace_path : xspace_paths) {
195 XSpace xspace;
196 Status status = ReadBinaryProto(Env::Default(), xspace_path, &xspace);
197 if (!status.ok()) {
198 LOG(WARNING) << "Could not read XSpace for tf data stats: "
199 << xspace_path;
200 return std::make_pair("", false);
201 }
202 XPlane* host_plane =
203 FindMutablePlaneWithName(&xspace, kHostThreadsPlaneName);
204 if (host_plane == nullptr) {
205 LOG(WARNING) << "Could not find host XPlane for tf data stats: "
206 << xspace_path;
207 return std::make_pair("", false);
208 }
209 absl::string_view host_name =
210 xspace.hostnames_size() ? xspace.hostnames(0) : xspace_path;
211 builder.Add(host_name, host_plane);
212 }
213 builder.Finalize();
214 return std::make_pair(combined_tf_data_stats.SerializeAsString(), true);
215 }
216
217 } // namespace
218
ConvertMultiXSpacesToToolData(const std::vector<std::string> & xspace_paths,const absl::string_view tool_name)219 std::pair<std::string, bool> ConvertMultiXSpacesToToolData(
220 const std::vector<std::string>& xspace_paths,
221 const absl::string_view tool_name) {
222 if (tool_name == "trace_viewer") {
223 return ConvertXSpaceToTraceEvents(xspace_paths);
224 } else if (tool_name == "overview_page") {
225 return ConvertMultiXSpacesToOverviewPage(xspace_paths);
226 } else if (tool_name == "input_pipeline_analyzer") {
227 return ConvertMultiXSpacesToInputPipeline(xspace_paths);
228 } else if (tool_name == "tensorflow_stats") {
229 return ConvertMultiXSpacesToTfStats(xspace_paths);
230 } else if (tool_name == "kernel_stats") {
231 return ConvertMultiXSpacesToKernelStats(xspace_paths);
232 } else if (tool_name == "memory_profile") {
233 return ConvertXSpaceToMemoryProfile(xspace_paths);
234 } else if (tool_name == "pod_viewer") {
235 return ConvertMultiXSpacesToPodViewer(xspace_paths);
236 } else if (tool_name == "tf_data_bottleneck_analysis") {
237 return ConvertMultiXSpacesToTfDataBottleneckAnalysis(xspace_paths);
238 } else {
239 LOG(WARNING) << "Can not find tool: " << tool_name << ". Please update to "
240 << "the latest version of Tensorflow.";
241 return std::make_pair("", false);
242 }
243 }
244
245 } // namespace profiler
246 } // namespace tensorflow
247