1/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7    http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#ifndef TENSORFLOW_COMPILER_XLA_METRIC_TABLE_REPORT_H_
17#define TENSORFLOW_COMPILER_XLA_METRIC_TABLE_REPORT_H_
18
19#include <vector>
20
21#include "tensorflow/compiler/xla/util.h"
22#include "tensorflow/core/lib/strings/str_util.h"
23#include "tensorflow/core/lib/strings/strcat.h"
24
25namespace xla {
26
27// Class for creating a text format table showing entries with a metric
28// (e.g. cycles) and a text (e.g. name of function taking that many
29// cycles). Entries are grouped by a category and sorted in decreasing order of
30// the metric.
31//
32// Example of a categories table generated using this class:
33//
34// ********** microseconds report **********
35// There are 3,912,517 microseconds in total.
36// There are 123 microseconds ( 0.00%) not accounted for by the data.
37// There are 3002 ops.
38//
39// ********** categories table **********
40// The left hand side numbers are microseconds.
41// 1,749,414 (44.71% Σ44.72%)   convolution (206 ops)
42//                             * 10.51% %convolution.202
43//                             * 10.51% %convolution.204
44//                             * 10.51% %convolution.203
45//                             * ... (203 more ops)
46//   884,939 (22.62% Σ67.33%)   convolution window-dilated (7 ops)
47//                             *  7.50% %convolution-window-dilated.7
48// [...]
49//
50// The entry table is similar, it just has the entries directly as the entries
51// instead of grouping by categories first.
52class MetricTableReport {
53 public:
54  // Represents an entry in the table.
55  struct Entry {
56    // Text to show in the entry table for this entry.
57    string text;
58
59    // Text to show in the category table for this entry.
60    string short_text;
61
62    // Text that represents the category of this entry - entries with the same
63    // category are grouped together in the category table.
64    string category_text;
65
66    // The value of the metric for this entry.
67    double metric = 0.0;
68  };
69
70  void AddEntry(Entry entry);
71
72  // The default name for the metric is "units", this function allows setting a
73  // more meaningful name.
74  void SetMetricName(string metric_name);
75
76  // The default name for referring to entries is "entries", this functions
77  // allows setting a more meaningful name.
78  void SetEntryName(string entry_name);
79
80  // By default the size of the table is limited. Calling this function forces
81  // all entries to be shown no matter how many there are.
82  void SetShowAllEntries();
83
84  // Set option to show a table with data on the categories of entries.
85  void SetShowCategoryTable();
86
87  // Set option to show a table with data on the entries.
88  void SetShowEntryTable();
89
90  // Returns the report as a string. expected_metric_sum is the expected sum of
91  // the metric across the entries. It is not an error for the actual sum to be
92  // different from the expectation - the report will include the
93  // discrepancy. All metric percentages are for the ratio with respect to the
94  // expected sum, not the actual sum.
95  string MakeReport(double expected_metric_sum);
96
97  // As MakeReport(), but writes the report to the INFO log in a way that avoids
98  // cutting the report off if it is longer than the maximum line length for a
99  // logged line. Individual lines in the report may still be cut off, but they
100  // would have to be very long for that to happen.
101  void WriteReportToInfoLog(double expected_metric_sum);
102
103 private:
104  static constexpr double kDefaultMaxMetricProportionToShow = 0.99;
105  static constexpr int64 kDefaultMaxEntriesToShow = 100;
106  static constexpr int64 kDefaultMaxEntriesPerCategoryToShow = 5;
107
108  // Append all parameters to the report.
109  template <typename... Args>
110  void AppendLine(Args... args) {
111    tensorflow::strings::StrAppend(&report_, std::forward<Args>(args)..., "\n");
112  }
113
114  // Represents a set of entries with the same category_text.
115  struct Category {
116    string category_text;
117    double metric_sum = 0.0;  // Sum of metric across entries.
118    std::vector<const Entry*> entries;
119  };
120
121  // Returns a vector of categories of entries with the same category_text. The
122  // vector is sorted in order of decreasing metric sum.
123  //
124  // The returned categories contain pointers into the entries parameter. The
125  // style guide requires parameters to which references/pointers are retained
126  // to be taken by pointer, even for const parameters, so that is why entries
127  // is taken by pointer.
128  static std::vector<Category> MakeCategories(
129      const std::vector<Entry>* entries);
130
131  // Append a header to the report.
132  void AppendHeader();
133
134  // Append a table of categories to the report.
135  void AppendCategoryTable();
136
137  // Append a table of entries to the report.
138  void AppendEntryTable();
139
140  // Appends a row of a table to the report.
141  void AppendTableRow(const string& text, const double metric,
142                      const double running_metric_sum);
143
144  // Returns the discrepancy between the expected sum of the metric of the
145  // entries and the actual sum.
146  double UnaccountedMetric();
147
148  // Formats the metric value as a string.
149  string MetricString(double metric);
150
151  // Returns a string representing the metric value as a proportion of the
152  // expected metric sum.
153  string MetricPercent(double metric);
154
155  // The entries to make a report about.
156  std::vector<Entry> entries_;
157
158  double expected_metric_sum_ = 0.0;
159  string metric_name_ = "units";
160  string entry_name_ = "entries";
161  bool show_category_table_ = false;
162  bool show_entry_table_ = false;
163
164  // These members control how many categories and entries to show in tables.
165  int64 max_entries_to_show_ = kDefaultMaxEntriesToShow;
166  int64 max_entries_per_category_to_show_ = kDefaultMaxEntriesPerCategoryToShow;
167  double max_metric_proportion_to_show_ = kDefaultMaxMetricProportionToShow;
168
169  // The report that is being created.
170  string report_;
171};
172
173}  // namespace xla
174
175#endif  // TENSORFLOW_COMPILER_XLA_METRIC_TABLE_REPORT_H_
176