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