The Sparta Modeling Framework
Loading...
Searching...
No Matches
Histogram.hpp
Go to the documentation of this file.
1// <Histogram.h> -*- C++ -*-
2
3
9#pragma once
10
11#include <iostream>
12#include <string>
13#include <vector>
14#include <algorithm>
15#include <numeric>
16#include "sparta/utils/MathUtils.hpp"
19#include "sparta/statistics/Counter.hpp"
23
24namespace sparta
25{
42{
43protected:
53 HistogramBase(uint64_t lower_val,
54 uint64_t upper_val,
55 uint32_t num_vals_per_bin) :
56 lower_val_(lower_val),
57 upper_val_(upper_val),
58 num_vals_per_bin_(num_vals_per_bin)
59 {
60 sparta_assert_context(upper_val > lower_val,
61 "Histogram: upper value must be greater than lower value");
62 sparta_assert_context(utils::is_power_of_2(num_vals_per_bin),
63 "Histogram: num_vals_per_bin must be power of 2");
64 idx_shift_amount_ = utils::floor_log2(num_vals_per_bin); // for quick devide
65 double actual_num_bins = (upper_val - lower_val)/num_vals_per_bin + 1;
66 num_bins_ = (uint64_t) actual_num_bins;
67 sparta_assert_context(actual_num_bins == num_bins_,
68 "Histogram: Actual number of bins (" << actual_num_bins
69 << ") is not an integer");
70 }
71
72public:
79 void addValue(uint64_t val)
80 {
81 ++(*total_values_);
82 *running_sum_ += val;
83
84 if (val < lower_val_) {
85 ++ (*underflow_bin_);
86 }
87 else if (val > upper_val_) {
88 ++ (*overflow_bin_);
89 }
90 else {
91 uint32_t idx = (val - lower_val_) >> idx_shift_amount_;
92 ++ (bin_.at(idx));
93 }
94 if (max_counters_.size()) {
96 }
97
98 }
99
105 double getStandardDeviation() const {
106
107 // Summation of counts in normal bins plus underflow bin and
108 // overflow bin.
109 const double sum = std::accumulate(bin_.begin(), bin_.end(), 0.0)
110 + (*underflow_bin_) + (*overflow_bin_);
111
112 // Total number of bins is number of regular bins
113 // plus one for underflow bin and plus one for
114 // overflow bin.
115 const std::size_t total_num_bins = bin_.size() + 2;
116
117 const double mean = sum / total_num_bins;
118 double accum = 0.0;
119 std::for_each(bin_.begin(), bin_.end(), [&](const sparta::Counter& c) {
120 auto c_get = c.get();
121 accum += pow(c_get - mean, 2);
122 });
123 accum += (*underflow_bin_ - mean) * (*underflow_bin_ - mean);
124 accum += (*overflow_bin_ - mean) * (*overflow_bin_ - mean);
125 return std::sqrt(accum / (total_num_bins - 1));
126 }
127
133 double getMeanBinCount() const {
134
135 // Summation of counts in normal bins plus underflow bin and
136 // overflow bin.
137 const double sum = std::accumulate(bin_.begin(), bin_.end(), 0.0)
138 + (*underflow_bin_) + (*overflow_bin_);
139
140 // Total number of bins is number of regular bins
141 // plus one for underflow bin and plus one for
142 // overflow bin.
143 const std::size_t total_num_bins = bin_.size() + 2;
144
145 return sum / total_num_bins;
146 }
147
152 return *total_values_;
153 }
154
158 const std::vector<sparta::Counter>& getRegularBin() const{
159 return bin_;
160 }
161
166 return *underflow_bin_;
167 }
168
173 return *overflow_bin_;
174 }
175
180 return ((static_cast<double>(*underflow_bin_))/(static_cast<double>(*total_values_)));
181 }
182
187 return ((static_cast<double>(*overflow_bin_))/(static_cast<double>(*total_values_)));
188 }
189
193 const std::vector<double>& recomputeRegularBinProbabilities() const{
194 bin_prob_vector_.clear();
195 for(const auto& b : bin_){
196 bin_prob_vector_.emplace_back(((static_cast<double>(b))/(static_cast<double>(*total_values_))));
197 }
198 return bin_prob_vector_;
199 }
200
201 uint64_t getHistogramUpperValue() const { return upper_val_; }
202 uint64_t getHistogramLowerValue() const { return lower_val_; }
203 uint32_t getNumBins() const { return num_bins_; }
204 uint32_t getNumValuesPerBin() const { return num_vals_per_bin_; }
205
206protected:
207
212 void updateMaxValues_(uint64_t val) {
213
214 // If the new value is less than everything already tracked, then
215 // there's nothing to update
216 auto min_it = max_values_.begin();
217 if (*min_it >= val) {
218 return;
219 }
220
221 max_values_.erase(min_it);
222 max_values_.insert(val);
223
224 uint32_t idx = 0;
225 for (auto it = max_values_.begin(); it != max_values_.end(); it++) {
226 sparta_assert(idx < max_counters_.size());
227 max_counters_[idx].set(*it);
228 idx++;
229 }
230 }
231
236 std::string getDisplayStringCumulative_(const std::string & name) const
237 {
238 std::stringstream str;
239 str << std::dec;
240 uint64_t running_sum = *underflow_bin_;
241 str << "\t" << name << "[ UF ] = " << running_sum << std::endl;
242 uint64_t start_val = lower_val_;
243 uint64_t end_val = start_val + num_vals_per_bin_ - 1;
244 for (uint32_t i=0; i<num_bins_; ++i) {
245 if (end_val > upper_val_)
246 end_val = upper_val_;
247 running_sum += (bin_[i]);
248 str << "\t" << name
249 << "[ " << start_val << "-" << end_val << " ] = "
250 << running_sum << std::endl;
251 end_val += num_vals_per_bin_;
252 }
253 running_sum += *overflow_bin_;
254 str << "\t" << name << "[ OF ] = " << running_sum << std::endl;
255 return str.str();
256 }
257
267 const std::string & stat_prefix = "",
270 uint32_t num_max_values = 0,
272
273 {
274 total_values_.reset(new sparta::Counter(sset,
275 stat_prefix + "total",
276 "Total values added to the histogram",
278 bin_vis));
279
280 running_sum_.reset(new sparta::Counter(sset,
281 stat_prefix + "sum",
282 "Sum of all values added to the histogram",
284 bin_vis));
285
286 // Reserve to use emplacement without tree child reordering
287 bin_.reserve(num_bins_);
288
289 underflow_bin_ = &sset->createCounter<sparta::Counter>(stat_prefix + "UF",
290 "underflow bin",
292 bin_vis);
293 underflow_probability_.reset(new StatisticDef(sset,
294 stat_prefix + "UF_probability",
295 "Probability of underflow",
296 sset,
297 stat_prefix + "UF" + "/" + stat_prefix + "total",
299 prob_vis));
300 uint64_t start_val = lower_val_;
301 uint64_t end_val = start_val + num_vals_per_bin_ - 1;
302 for (uint32_t i=0; i<num_bins_; ++i) {
303 if (end_val > upper_val_)
304 end_val = upper_val_;
305 std::stringstream str;
306 str << stat_prefix << "bin_" << start_val << "_" << end_val;
307 bin_.emplace_back(sparta::Counter(sset,
308 str.str(),
309 str.str() + " histogram bin",
311 bin_vis));
312 probabilities_.emplace_back(new StatisticDef(sset,
313 str.str() + "_probability",
314 str.str() + " bin probability",
315 sset,
316 str.str() + "/" + stat_prefix + "total",
318 prob_vis));
319 start_val = end_val + 1;
320 end_val += num_vals_per_bin_;
321 }
322 overflow_bin_ = &sset->createCounter<sparta::Counter>(stat_prefix + "OF",
323 stat_prefix + "overflow bin",
325 bin_vis);
326 overflow_probability_.reset(new StatisticDef(sset,
327 stat_prefix + "OF_probability",
328 "Probability of overflow",
329 sset,
330 stat_prefix + "OF" + "/" + stat_prefix + "total",
332 prob_vis));;
333
334 average_.reset(new StatisticDef(sset,
335 stat_prefix + "average",
336 "Average of all values added to the histogram",
337 sset,
338 stat_prefix + "sum" + "/" + stat_prefix + "total",
341
342 if (num_max_values > 0) {
343 max_counters_.reserve(num_max_values);
344 for (uint32_t idx = 0; idx < num_max_values; idx++) {
345 std::stringstream mvtext;
346 mvtext << "maxval" << idx;
347 max_counters_.emplace_back(sset,
348 stat_prefix + mvtext.str(),
349 stat_prefix + " maximum value",
351 max_vis);
352 max_counters_[idx].set(0); // Counters can't have -1, so use '0' for uninitialized :-/
353 max_values_.insert(0);
354 }
355 }
356 }
357
358
359private:
360 const uint64_t lower_val_;
361 const uint64_t upper_val_;
362 const uint32_t num_vals_per_bin_;
363
364 std::unique_ptr<sparta::Counter> total_values_;
365 std::unique_ptr<sparta::Counter> running_sum_;
366 sparta::Counter* underflow_bin_;
367 sparta::Counter* overflow_bin_;
368 std::vector<sparta::Counter> bin_;
369 std::unique_ptr<sparta::StatisticDef> underflow_probability_;
370 std::unique_ptr<sparta::StatisticDef> overflow_probability_;
371 std::vector<std::unique_ptr<sparta::StatisticDef>> probabilities_;
372 std::unique_ptr<sparta::StatisticDef> average_;
373
374 std::vector<sparta::Counter> max_counters_;
375 std::multiset<uint64_t> max_values_;
376
377 uint32_t num_bins_;
378
382 uint32_t idx_shift_amount_;
383 mutable std::vector<double> bin_prob_vector_;
384};
385
387
389{
390public:
404 const std::string & stat_prefix,
405 uint64_t lower_val,
406 uint64_t upper_val,
407 uint32_t num_vals_per_bin,
408 uint32_t num_max_vals,
412 HistogramBase(lower_val, upper_val, num_vals_per_bin)
413 {
414 initializeStats_(sset, stat_prefix, bin_vis, prob_vis, num_max_vals, max_vis);
415 }
416
417};
418
420
426{
427public:
428
433
438
443
447 void operator=(const HistogramTreeNode&) = delete;
448
463 HistogramTreeNode(TreeNode* parent_treenode,
464 const std::string & histogram_name,
465 const std::string & description,
466 uint64_t lower_val,
467 uint64_t upper_val,
468 uint32_t num_vals_per_bin,
471 TreeNode(histogram_name, description),
472 HistogramBase(lower_val, upper_val, num_vals_per_bin),
473 sset_(this)
474 {
475 initializeStats_(parent_treenode, 0, bin_vis, prob_vis,
477 }
478
479 HistogramTreeNode(TreeNode * parent_treenode,
480 const std::string & histogram_name,
481 const std::string & description,
482 const uint64_t lower_val,
483 const uint64_t upper_val,
484 const uint32_t num_vals_per_bin,
485 const uint32_t num_max_values,
487 const InstrumentationNode::Visibility prob_vis) :
488 TreeNode(histogram_name, description),
489 HistogramBase(lower_val, upper_val, num_vals_per_bin),
490 sset_(this)
491 {
492 initializeStats_(parent_treenode, num_max_values, bin_vis, prob_vis,
494 }
495
496 std::string getDisplayStringCumulative() const {
498 }
499
500
501private:
502 void initializeStats_(TreeNode * parent_treenode,
503 const uint32_t num_max_values,
505 const InstrumentationNode::Visibility prob_vis,
507 {
508 if(parent_treenode){
509 setExpectedParent_(parent_treenode);
510 }
511
513 &sset_, "", bin_vis, prob_vis, num_max_values, max_vis);
514
515 if(parent_treenode){
516 parent_treenode->addChild(this);
517 }
518 }
519
521
522}; // class HistogramTreeNode
523
524// Maintain backwards compatibility with the legacy Histogram class that
525// was always a TreeNode
526typedef HistogramTreeNode Histogram;
527
528} // namespace sparta
File that defines the Resource class. Consider using sparta::Unit instead.
#define sparta_assert_context(e, insertions)
Check condition and throw a sparta exception if condition evaluates to false or 0....
Definition Resource.hpp:402
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Contains a statistic definition (some useful information which can be computed)
File that defines the StatisticSet class.
Basic Node framework in sparta device tree composite pattern.
@ COUNT_LATEST
Counter holds the latest value (from most recent activity) and can increase or decrease at any time.
@ COUNT_NORMAL
Counter counts the number of times something happens like one would expect. This is a weakly monotoni...
Represents a counter of type counter_type (uint64_t). 2 and greater than 0 with a ceiling specified....
Definition Counter.hpp:27
Histogram base class for uint64_t values.
Definition Histogram.hpp:42
double getOverflowProbability() const
Return overflow probability.
const sparta::Counter & getUnderflowBin() const
Return count of underflow bin.
const std::vector< double > & recomputeRegularBinProbabilities() const
Return vector of probabilities regular bins.
double getStandardDeviation() const
Calculate Standard Deviation of counts in bins. This API also takes into account the count in underfl...
const sparta::Counter & getAggValues() const
Return aggregate of this histogram.
double getUnderflowProbability() const
Return underflow probability.
const sparta::Counter & getOverflowBin() const
Return count of overflow bin.
void addValue(uint64_t val)
Add a value to histogram.
Definition Histogram.hpp:79
void initializeStats_(StatisticSet *sset, const std::string &stat_prefix="", InstrumentationNode::Visibility bin_vis=InstrumentationNode::VIS_NORMAL, InstrumentationNode::Visibility prob_vis=InstrumentationNode::VIS_NORMAL, uint32_t num_max_values=0, InstrumentationNode::Visibility max_vis=InstrumentationNode::VIS_SUMMARY)
const std::vector< sparta::Counter > & getRegularBin() const
Return vector of regular bin counts.
void updateMaxValues_(uint64_t val)
HistogramBase(uint64_t lower_val, uint64_t upper_val, uint32_t num_vals_per_bin)
HistogramBase constructor.
Definition Histogram.hpp:53
std::string getDisplayStringCumulative_(const std::string &name) const
Render the cumulative values of this histogram for use in standalone model.
double getMeanBinCount() const
Calculate the mean bin count of all the bins. This API also takes into account the count in underflow...
HistogramStandalone(StatisticSet *sset, const std::string &stat_prefix, uint64_t lower_val, uint64_t upper_val, uint32_t num_vals_per_bin, uint32_t num_max_vals, InstrumentationNode::Visibility bin_vis=InstrumentationNode::VIS_NORMAL, InstrumentationNode::Visibility prob_vis=InstrumentationNode::VIS_NORMAL, InstrumentationNode::Visibility max_vis=InstrumentationNode::VIS_NORMAL)
HistogramTreeNode(TreeNode *parent_treenode, const std::string &histogram_name, const std::string &description, uint64_t lower_val, uint64_t upper_val, uint32_t num_vals_per_bin, InstrumentationNode::Visibility bin_vis=InstrumentationNode::VIS_NORMAL, InstrumentationNode::Visibility prob_vis=InstrumentationNode::VIS_NORMAL)
HistogramTreeNode constructor.
HistogramTreeNode(HistogramTreeNode &&)=delete
Not move-constructable.
HistogramTreeNode(const HistogramTreeNode &)=delete
Not copy-constructable.
void operator=(const HistogramTreeNode &)=delete
Not assignable.
HistogramTreeNode()=delete
Not default constructable.
Visibility
Common visibility levels. Visibility is a continum (visibility can be anywhere in [0 to MAX_VISIBILIT...
@ VIS_SUMMARY
The next two visibility levels are for High-importance data. These are split up in the (100M,...
@ VIS_NORMAL
Normal visibility (default)
Contains a statistic definition (some useful information which can be computed)
@ VS_FRACTIONAL
A fractional number. This value should be in the range [0,1]. Some report formatters could show this ...
@ VS_ABSOLUTE
An absolute number having no units (typical default)
Set of StatisticDef and CounterBase-derived objects for visiblility through a sparta Tree.
CounterT & createCounter(_Args &&... __args)
Allocates a Counter which is owned by this StatisticSet and deleted at its destruction.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
TreeNode()=delete
Not default-constructable.
const std::string & getName() const override
Gets the name of this node.
void setExpectedParent_(const TreeNode *parent)
Tracks a node as an expected parent without actually adding this node as a child. This is used almost...
Macros for handling exponential backoff.