1 /* Copyright 2015 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 #ifndef TENSORFLOW_CORE_LIB_HISTOGRAM_HISTOGRAM_H_ 17 #define TENSORFLOW_CORE_LIB_HISTOGRAM_HISTOGRAM_H_ 18 19 #include <string> 20 #include <vector> 21 #include "tensorflow/core/lib/gtl/array_slice.h" 22 #include "tensorflow/core/platform/macros.h" 23 #include "tensorflow/core/platform/mutex.h" 24 #include "tensorflow/core/platform/thread_annotations.h" 25 #include "tensorflow/core/platform/types.h" 26 27 namespace tensorflow { 28 29 class HistogramProto; 30 31 namespace histogram { 32 33 class Histogram { 34 public: 35 // Create a histogram with a default set of bucket boundaries. 36 // Buckets near zero cover very small ranges (e.g. 10^-12), and each 37 // bucket range grows by ~10% as we head away from zero. The 38 // buckets cover the range from -DBL_MAX to DBL_MAX. 39 Histogram(); 40 41 // Create a histogram with a custom set of bucket boundaries, 42 // specified in "custom_bucket_limits[0..custom_bucket_limits.size()-1]" 43 // REQUIRES: custom_bucket_limits[i] values are monotonically increasing. 44 // REQUIRES: custom_bucket_limits is not empty() 45 explicit Histogram(gtl::ArraySlice<double> custom_bucket_limits); 46 47 // Restore the state of a histogram that was previously encoded 48 // via Histogram::EncodeToProto. Note that only the bucket boundaries 49 // generated by EncodeToProto will be restored. 50 bool DecodeFromProto(const HistogramProto& proto); 51 ~Histogram()52 ~Histogram() {} 53 54 void Clear(); 55 void Add(double value); 56 57 // Save the current state of the histogram to "*proto". If 58 // "preserve_zero_buckets" is false, only non-zero bucket values and 59 // ranges are saved, and the bucket boundaries of zero-valued buckets 60 // are lost. 61 void EncodeToProto(HistogramProto* proto, bool preserve_zero_buckets) const; 62 63 // Return the median of the values in the histogram 64 double Median() const; 65 66 // Return the "p"th percentile [0.0..100.0] of the values in the 67 // distribution 68 double Percentile(double p) const; 69 70 // Return the average value of the distribution 71 double Average() const; 72 73 // Return the standard deviation of values in the distribution 74 double StandardDeviation() const; 75 76 // Returns a multi-line human-readable string representing the histogram 77 // contents. Example output: 78 // Count: 4 Average: 251.7475 StdDev: 432.02 79 // Min: -3.0000 Median: 5.0000 Max: 1000.0000 80 // ------------------------------------------------------ 81 // [ -5, 0 ) 1 25.000% 25.000% ##### 82 // [ 0, 5 ) 1 25.000% 50.000% ##### 83 // [ 5, 10 ) 1 25.000% 75.000% ##### 84 // [ 1000, 10000 ) 1 25.000% 100.000% ##### 85 std::string ToString() const; 86 87 private: 88 double min_; 89 double max_; 90 double num_; 91 double sum_; 92 double sum_squares_; 93 94 std::vector<double> custom_bucket_limits_; 95 gtl::ArraySlice<double> bucket_limits_; 96 std::vector<double> buckets_; 97 98 double Remap(double x, double x0, double x1, double y0, double y1) const; 99 100 TF_DISALLOW_COPY_AND_ASSIGN(Histogram); 101 }; 102 103 // Wrapper around a Histogram object that is thread safe. 104 // 105 // All methods hold a lock while delegating to a Histogram object owned by the 106 // ThreadSafeHistogram instance. 107 // 108 // See Histogram for documentation of the methods. 109 class ThreadSafeHistogram { 110 public: ThreadSafeHistogram()111 ThreadSafeHistogram() {} ThreadSafeHistogram(gtl::ArraySlice<double> custom_bucket_limits)112 explicit ThreadSafeHistogram(gtl::ArraySlice<double> custom_bucket_limits) 113 : histogram_(custom_bucket_limits) {} 114 bool DecodeFromProto(const HistogramProto& proto); 115 ~ThreadSafeHistogram()116 ~ThreadSafeHistogram() {} 117 118 void Clear(); 119 120 // TODO(touts): It might be a good idea to provide a AddN(<many values>) 121 // method to avoid grabbing/releasing the lock when adding many values. 122 void Add(double value); 123 124 void EncodeToProto(HistogramProto* proto, bool preserve_zero_buckets) const; 125 double Median() const; 126 double Percentile(double p) const; 127 double Average() const; 128 double StandardDeviation() const; 129 std::string ToString() const; 130 131 private: 132 mutable mutex mu_; 133 Histogram histogram_ GUARDED_BY(mu_); 134 }; 135 136 } // namespace histogram 137 } // namespace tensorflow 138 139 #endif // TENSORFLOW_CORE_LIB_HISTOGRAM_HISTOGRAM_H_ 140