SST  6.1.0
StructuralSimulationToolkit
stathistogram.h
1 // Copyright 2009-2016 Sandia Corporation. Under the terms
2 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2016, Sandia Corporation
6 // All rights reserved.
7 //
8 // This file is part of the SST software package. For license
9 // information, see the LICENSE file in the top level directory of the
10 // distribution.
11 
12 
13 #ifndef _H_SST_CORE_HISTOGRAM_STATISTIC_
14 #define _H_SST_CORE_HISTOGRAM_STATISTIC_
15 
16 #include <sst/core/sst_types.h>
17 
18 #include <sst/core/statapi/statbase.h>
19 
20 namespace SST {
21 namespace Statistics {
22 
23 // NOTE: When calling base class members in classes derived from
24 // a templated base class. The user must use "this->" in
25 // order to call base class members (to avoid a compilier
26 // error) because they are "nondependant named" and the
27 // templated base class is a "dependant named". The
28 // compilier will not look in dependant named base classes
29 // when looking up independant names.
30 // See: http://www.parashift.com/c++-faq-lite/nondependent-name-lookup-members.html
31 
32 /**
33  \class HistogramStatistic
34  Holder of data grouped into pre-determined width bins.
35  \tparam BinDataType is the type of the data held in each bin (i.e. what data type described the width of the bin)
36 */
37 #define CountType uint64_t
38 #define NumBinsType uint32_t
39 
40 template<class BinDataType>
41 class HistogramStatistic : public Statistic<BinDataType>
42 {
43 private:
44  friend class SST::Component;
45 
46  HistogramStatistic(Component* comp, std::string& statName, std::string& statSubId, Params& statParams)
47  : Statistic<BinDataType>(comp, statName, statSubId, statParams)
48  {
49  // Identify what keys are Allowed in the parameters
50  Params::KeySet_t allowedKeySet;
51  allowedKeySet.insert("minvalue");
52  allowedKeySet.insert("binwidth");
53  allowedKeySet.insert("numbins");
54  allowedKeySet.insert("dumpbinsonoutput");
55  allowedKeySet.insert("includeoutofbounds");
56  statParams.pushAllowedKeys(allowedKeySet);
57 
58  // Process the Parameters
59  m_minValue = statParams.find<BinDataType>("minvalue", 0);
60  m_binWidth = statParams.find<NumBinsType>("binwidth", 5000);
61  m_numBins = statParams.find<NumBinsType>("numbins", 100);
62  m_dumpBinsOnOutput = statParams.find<bool>("dumpbinsonoutput", true);
63  m_includeOutOfBounds = statParams.find<bool>("includeoutofbounds", true);
64 
65  // Initialize other properties
66  m_totalSummed = 0;
67  m_totalSummedSqr = 0;
68  m_OOBMinCount = 0;
69  m_OOBMaxCount = 0;
70  m_itemsBinnedCount = 0;
71  this->setCollectionCount(0);
72 
73  // Set the Name of this Statistic
74  this->setStatisticTypeName("Histogram");
75  }
76 
77  ~HistogramStatistic() {}
78 
79 protected:
80  /**
81  Adds a new value to the histogram. The correct bin is identified and then incremented. If no bin can be found
82  to hold the value then a new bin is created.
83  */
84  void addData_impl(BinDataType value)
85  {
86  // Check to see if the value is above or below the min/max values
87  if (value < getBinsMinValue()) {
88  m_OOBMinCount++;
89  return;
90  }
91  if (value > getBinsMaxValue()) {
92  m_OOBMaxCount++;
93  return;
94  }
95 
96  // This value is to be binned...
97  // Add the "in limits" value to the total summation's
98  m_totalSummed += value;
99  m_totalSummedSqr += (value * value);
100 
101  // Increment the Binned count (note this <= to the Statistics added Item Count)
102  m_itemsBinnedCount++;
103 
104  // Figure out what the starting bin is and find it in the map
105  // To support signed and unsigned values along with floating point types,
106  // the calculation to find the bin_start value must be done in floating point
107  // then converted to BinDataType
108  double calc1 = (double)value / (double)m_binWidth;
109  double calc2 = floor(calc1); // Find the floor of the value
110  double calc3 = m_binWidth * calc2;
111  BinDataType bin_start = (BinDataType)calc3;
112 // printf("DEBUG: value = %d, junk1 = %f, calc2 = %f, calc3 = %f : bin_start = %d, item count = %ld, \n", value, calc1, calc2, calc3, bin_start, getStatCollectionCount());
113 
114  HistoMapItr_t bin_itr = m_binsMap.find(bin_start);
115 
116  // Was the bin found?
117  if(bin_itr == m_binsMap.end()) {
118  // No, Create the bin and set a value of 1 to it
119  m_binsMap.insert(std::pair<BinDataType, CountType>(bin_start, (CountType) 1));
120  } else {
121  // Yes, Increment the specific bin's count
122  bin_itr->second++;
123  }
124  }
125 
126 private:
127  /** Count how many bins are active in this histogram */
128  NumBinsType getActiveBinCount()
129  {
130  return m_binsMap.size();
131  }
132 
133  /** Count how many bins are available */
134  NumBinsType getNumBins()
135  {
136  return m_numBins;
137  }
138 
139  /** Get the width of a bin in this histogram */
140  NumBinsType getBinWidth()
141  {
142  return m_binWidth;
143  }
144 
145  /**
146  Get the count of items in the bin by the start value (e.g. give me the count of items in the bin which begins at value X).
147  \return The count of items in the bin else 0.
148  */
149  CountType getBinCountByBinStart(BinDataType binStartValue)
150  {
151  // Find the Bin Start Value in the Bin Map
152  HistoMapItr_t bin_itr = m_binsMap.find(binStartValue);
153 
154  // Check to see if the Start Value was found
155  if(bin_itr == m_binsMap.end()) {
156  // No, return no count for this bin
157  return (CountType) 0;
158  } else {
159  // Yes, return the bin count
160  return m_binsMap[binStartValue];
161  }
162  }
163 
164  /**
165  Get the smallest start value of a bin in this histogram (i.e. the minimum value possibly represented by this histogram)
166  */
167  BinDataType getBinsMinValue()
168  {
169  return m_minValue;
170  }
171 
172  /**
173  Get the largest possible value represented by this histogram (i.e. the highest value in any of items bins rounded above to the size of the bin)
174  */
175  BinDataType getBinsMaxValue()
176  {
177  // Compute the max value based on the width * num bins offset by minvalue
178  return (m_binWidth * m_numBins) + m_minValue - 1;
179  }
180 
181  /**
182  Get the total number of items collected by the statistic
183  \return The number of items that have been added to the statistic
184  */
185  uint64_t getStatCollectionCount()
186  {
187  // Get the number of items added (but not necessarily binned) to this statistic
188  return this->getCollectionCount();
189  }
190 
191  /**
192  Get the total number of items contained in all bins
193  \return The number of items contained in all bins
194  */
195  CountType getItemsBinnedCount()
196  {
197  // Get the number of items added to this statistic that were binned.
198  return m_itemsBinnedCount;
199  }
200 
201  /**
202  Sum up every item presented for storage in the histogram
203  \return The sum of all values added into the histogram
204  */
205  BinDataType getValuesSummed()
206  {
207  return m_totalSummed;
208  }
209 
210  /**
211  Sum up every squared value entered into the Histogram.
212  \return The sum of all values added after squaring into the Histogram
213  */
214  BinDataType getValuesSquaredSummed() {
215  return m_totalSummedSqr;
216  }
217 
218  void clearStatisticData()
219  {
220  m_totalSummed = 0;
221  m_totalSummedSqr = 0;
222  m_OOBMinCount = 0;
223  m_OOBMaxCount = 0;
224  m_itemsBinnedCount = 0;
225  m_binsMap.clear();
226  this->setCollectionCount(0);
227  }
228 
229  void registerOutputFields(StatisticOutput* statOutput)
230  {
231  // Check to see if we have registered the Startup Fields
232  m_Fields.push_back(statOutput->registerField<BinDataType>("BinsMinValue"));
233  m_Fields.push_back(statOutput->registerField<BinDataType>("BinsMaxValue"));
234  m_Fields.push_back(statOutput->registerField<NumBinsType>("BinWidth"));
235  m_Fields.push_back(statOutput->registerField<NumBinsType>("TotalNumBins"));
236  m_Fields.push_back(statOutput->registerField<BinDataType>("Sum"));
237  m_Fields.push_back(statOutput->registerField<BinDataType>("SumSQ"));
238  m_Fields.push_back(statOutput->registerField<NumBinsType>("NumActiveBins"));
239  m_Fields.push_back(statOutput->registerField<CountType> ("NumItemsCollected"));
240  m_Fields.push_back(statOutput->registerField<CountType> ("NumItemsBinned"));
241 
242  if (true == m_includeOutOfBounds) {
243  m_Fields.push_back(statOutput->registerField<CountType>("NumOutOfBounds-MinValue"));
244  m_Fields.push_back(statOutput->registerField<CountType>("NumOutOfBounds-MaxValue"));
245  }
246 
247  // Do we also need to dump the bin counts on output
248  if (true == m_dumpBinsOnOutput) {
249  BinDataType binLL;
250  BinDataType binUL;
251 
252  for (uint32_t y = 0; y < getNumBins(); y++) {
253  // Figure out the upper and lower values for this bin
254  binLL = (y * (uint64_t)getBinWidth()) + getBinsMinValue(); // Force full 64-bit multiply -mpf 10/8/15
255  binUL = binLL + getBinWidth() - 1;
256  // Build the string name for this bin and add it as a field
257  std::stringstream ss;
258  ss << "Bin" << y << ":" << binLL << "-" << binUL;
259  m_Fields.push_back(statOutput->registerField<CountType>(ss.str().c_str()));
260  }
261  }
262  }
263 
264  void outputStatisticData(StatisticOutput* statOutput, bool EndOfSimFlag)
265  {
266  uint32_t x = 0;
267  statOutput->outputField(m_Fields[x++], getBinsMinValue());
268  statOutput->outputField(m_Fields[x++], getBinsMaxValue());
269  statOutput->outputField(m_Fields[x++], getBinWidth());
270  statOutput->outputField(m_Fields[x++], getNumBins());
271  statOutput->outputField(m_Fields[x++], getValuesSummed());
272  statOutput->outputField(m_Fields[x++], getValuesSquaredSummed());
273  statOutput->outputField(m_Fields[x++], getActiveBinCount());
274  statOutput->outputField(m_Fields[x++], getStatCollectionCount());
275  statOutput->outputField(m_Fields[x++], getItemsBinnedCount());
276 
277  if (true == m_includeOutOfBounds) {
278  statOutput->outputField(m_Fields[x++], m_OOBMinCount);
279  statOutput->outputField(m_Fields[x++], m_OOBMaxCount);
280  }
281 
282  // Do we also need to dump the bin counts on output
283  if (true == m_dumpBinsOnOutput) {
284  BinDataType currentBinValue = getBinsMinValue();
285  for (uint32_t y = 0; y < getNumBins(); y++) {
286  statOutput->outputField(m_Fields[x++], getBinCountByBinStart(currentBinValue));
287  // Increment the currentBinValue to get the next bin
288  currentBinValue += getBinWidth();
289  }
290  }
291  }
292 
293  bool isStatModeSupported(StatisticBase::StatMode_t mode) const
294  {
295  if (mode == StatisticBase::STAT_MODE_COUNT) {
296  return true;
297  }
298  if (mode == StatisticBase::STAT_MODE_PERIODIC) {
299  return true;
300  }
301  return false;
302  }
303 
304 private:
305  // Bin Map Definition
306  typedef std::map<BinDataType, CountType> HistoMap_t;
307 
308  // Iterator over the histogram bins
309  typedef typename HistoMap_t::iterator HistoMapItr_t;
310 
311  // The minimum value in the Histogram
312  BinDataType m_minValue;
313 
314  // The width of each Histogram bin
315  NumBinsType m_binWidth;
316 
317  // The number of bins to be supported
318  NumBinsType m_numBins;
319 
320  // Out of bounds bins
321  CountType m_OOBMinCount;
322  CountType m_OOBMaxCount;
323 
324  // Count of Items that have binned, (Different than item count as some
325  // items may be out of bounds and not binned)
326  CountType m_itemsBinnedCount;
327 
328  // The sum of all values added into the Histogram, this is calculated and the sum of all values presented
329  // to be entered into the Histogram not with bin-width multiplied by the (max-min)/2 of the bin.
330  BinDataType m_totalSummed;
331 
332  // The sum of values added to the Histogram squared. Allows calculation of derivative statistic
333  // values such as variance.
334  BinDataType m_totalSummedSqr;
335 
336  // A map of the the bin starts to the bin counts
337  HistoMap_t m_binsMap;
338 
339  // Support
340  std::vector<uint32_t> m_Fields;
341  bool m_dumpBinsOnOutput;
342  bool m_includeOutOfBounds;
343 
344 };
345 
346 } //namespace Statistics
347 } //namespace SST
348 
349 #endif
void pushAllowedKeys(const KeySet_t &keys)
Definition: params.h:478
Main component object for the simulation.
Definition: component.h:56
void setStatisticTypeName(const char *typeName)
Set an optional Statistic Type Name.
Definition: statbase.h:177
Definition: action.cc:17
uint64_t getCollectionCount() const
Return the current collection count.
Definition: statbase.h:120
Holder of data grouped into pre-determined width bins.
Definition: stathistogram.h:41
Forms the template defined base class for statistics gathering within SST.
Definition: statbase.h:263
void addData_impl(BinDataType value)
Adds a new value to the histogram.
Definition: stathistogram.h:84
T find(const std::string &k, T default_value, bool &found) const
Find a Parameter value in the set, and return its value as a type T.
Definition: params.h:163
StatMode_t
Statistic collection mode.
Definition: statbase.h:40
Parameter store.
Definition: params.h:44
std::set< key_type, KeyCompare > KeySet_t
Definition: params.h:93
virtual void setCollectionCount(uint64_t newCount)
Set the current collection count to a defined value.
Definition: statbase.cc:41