1 /* Copyright 2019 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/op_stats_to_tf_stats.h"
17
18 #include "tensorflow/core/platform/types.h"
19 #include "tensorflow/core/profiler/convert/op_metrics_to_record.h"
20 #include "tensorflow/core/profiler/protobuf/op_metrics.pb.h"
21 #include "tensorflow/core/profiler/protobuf/op_stats.pb.h"
22 #include "tensorflow/core/profiler/protobuf/tf_stats.pb.h"
23 #include "tensorflow/core/profiler/utils/kernel_stats_utils.h"
24 #include "tensorflow/core/profiler/utils/math_utils.h"
25 #include "tensorflow/core/profiler/utils/op_metrics_db_utils.h"
26
27 namespace tensorflow {
28 namespace profiler {
29 namespace {
30
31 // The maximum number of Tensorflow Ops displayed on Tensorflow Stats page.
32 // 500 device side ops and 500 host side ops.
33 const int kMaxNumOfOps = 500;
34
ConvertOpMetricsToTfStatsRecord(bool on_device,const OpMetrics & metrics,double ridge_point_operational_intensity)35 TfStatsRecord ConvertOpMetricsToTfStatsRecord(
36 bool on_device, const OpMetrics& metrics,
37 double ridge_point_operational_intensity) {
38 TfStatsRecord record;
39 record.set_host_or_device(on_device ? "Device" : "Host");
40 record.set_is_eager(metrics.is_eager());
41 record.set_op_type(metrics.category());
42 record.set_op_name(metrics.name());
43 SetExecutionTimes(metrics, &record);
44 SetRooflineMetrics(metrics, ridge_point_operational_intensity, &record);
45 return record;
46 }
47
GenerateTfStatsTable(const OpMetricsDb & host_tf_metrics_db,const OpMetricsDb & device_tf_metrics_db,const KernelStatsByOpName & kernel_stats_by_op_name,double ridge_point,bool exclude_idle)48 TfStatsTable GenerateTfStatsTable(
49 const OpMetricsDb& host_tf_metrics_db,
50 const OpMetricsDb& device_tf_metrics_db,
51 const KernelStatsByOpName& kernel_stats_by_op_name, double ridge_point,
52 bool exclude_idle) {
53 TfStatsTable tf_stats_table;
54 TfStatsRecord sentinel;
55 sentinel.set_rank(0);
56 sentinel.set_device_cumulative_total_self_time_as_fraction(0.0);
57 sentinel.set_host_cumulative_total_self_time_as_fraction(0.0);
58 const TfStatsRecord* prev_record = &sentinel;
59
60 // Sets device-side TF stats.
61 uint64 total_device_time_ps = TotalTimePs(device_tf_metrics_db, exclude_idle);
62 double total_device_time_us = PicoToMicro(total_device_time_ps);
63 for (const OpMetrics* metrics :
64 SortedOpMetricsDb(device_tf_metrics_db, kMaxNumOfOps)) {
65 if (exclude_idle && IsIdleOp(*metrics)) continue;
66 TfStatsRecord* record = tf_stats_table.add_tf_stats_record();
67 *record = ConvertOpMetricsToTfStatsRecord(
68 /*on_device=*/true, *metrics, ridge_point);
69 // Compute TensorCore utilization only on device side.
70 auto iter = kernel_stats_by_op_name.find(record->op_name());
71 if (iter != kernel_stats_by_op_name.end()) {
72 record->set_gpu_tensorcore_utilization(
73 SafeDivide(iter->second.tensor_core_duration_ns,
74 iter->second.total_duration_ns));
75 } else {
76 record->set_gpu_tensorcore_utilization(0.0);
77 }
78 SetRankAndDeviceTimeFractions(total_device_time_us, *prev_record, record);
79 prev_record = record;
80 }
81
82 // Sets host-side TF stats.
83 uint64 total_host_time_ps = TotalTimePs(host_tf_metrics_db, exclude_idle);
84 double total_host_time_us = PicoToMicro(total_host_time_ps);
85 for (const OpMetrics* metrics : tensorflow::profiler::SortedOpMetricsDb(
86 host_tf_metrics_db, kMaxNumOfOps)) {
87 if (exclude_idle && IsIdleOp(*metrics)) continue;
88 TfStatsRecord* record = tf_stats_table.add_tf_stats_record();
89 *record = ConvertOpMetricsToTfStatsRecord(
90 /*on_device=*/false, *metrics, ridge_point);
91 // Host side TensorCore utilization is always 0.0
92 record->set_gpu_tensorcore_utilization(0.0);
93 SetRankAndHostTimeFractions(total_host_time_us, *prev_record, record);
94 prev_record = record;
95 }
96 return tf_stats_table;
97 }
98
99 } // namespace
100
ConvertOpStatsToTfStats(const OpStats & op_stats)101 TfStatsDatabase ConvertOpStatsToTfStats(const OpStats& op_stats) {
102 const OpMetricsDb& host_tf_metrics_db = op_stats.host_op_metrics_db();
103 OpMetricsDb device_tf_metrics_db =
104 CreateTfMetricsDbFromDeviceOpMetricsDb(op_stats.device_op_metrics_db());
105 double ridge_point = op_stats.perf_env().ridge_point();
106 KernelStatsByOpName kernel_stats_by_op_name =
107 GroupKernelReportsByOpName(op_stats.kernel_stats_db());
108 TfStatsDatabase tf_stats_db;
109 *tf_stats_db.mutable_with_idle() = GenerateTfStatsTable(
110 host_tf_metrics_db, device_tf_metrics_db, kernel_stats_by_op_name,
111 ridge_point, /*exclude_idle=*/false);
112 *tf_stats_db.mutable_without_idle() = GenerateTfStatsTable(
113 host_tf_metrics_db, device_tf_metrics_db, kernel_stats_by_op_name,
114 ridge_point, /*exclude_idle=*/true);
115 tf_stats_db.set_device_type(op_stats.run_environment().device_type());
116 return tf_stats_db;
117 }
118
119 } // namespace profiler
120 } // namespace tensorflow
121