xref: /aosp_15_r20/external/tensorflow/tensorflow/core/profiler/convert/op_stats_to_tf_stats.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
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