changeset c1e158414648 in /z/repo/m5
details: http://repo.m5sim.org/m5?cmd=changeset;node=c1e158414648
description:
        stats: Add a histogram statistic type

diffstat:

 src/base/statistics.cc   |   83 +++++++++++++++++++++++
 src/base/statistics.hh   |  163 +++++++++++++++++++++++++++++++++++++++++++++++
 src/base/stats/info.hh   |    2 +-
 src/base/stats/text.cc   |   12 +-
 src/unittest/stattest.cc |  112 ++++++++++++++++++++++++++++++++
 5 files changed, 365 insertions(+), 7 deletions(-)

diffs (truncated from 472 to 300 lines):

diff -r 8bdcec97b36b -r c1e158414648 src/base/statistics.cc
--- a/src/base/statistics.cc    Mon Jan 10 11:11:17 2011 -0800
+++ b/src/base/statistics.cc    Mon Jan 10 11:11:17 2011 -0800
@@ -236,6 +236,89 @@
         y_subnames.resize(y);
 }
 
+void
+HistStor::grow_out()
+{
+    int size = cvec.size();
+    int zero = size / 2; // round down!
+    int top_half = zero + (size - zero + 1) / 2; // round up!
+    int bottom_half = (size - zero) / 2; // round down!
+
+    // grow down
+    int low_pair = zero - 1;
+    for (int i = zero - 1; i >= bottom_half; i--) {
+        cvec[i] = cvec[low_pair];
+        if (low_pair - 1 >= 0)
+            cvec[i] += cvec[low_pair - 1];
+        low_pair -= 2;
+    }
+    assert(low_pair == 0 || low_pair == -1 || low_pair == -2);
+
+    for (int i = bottom_half - 1; i >= 0; i--)
+        cvec[i] = Counter();
+
+    // grow up
+    int high_pair = zero;
+    for (int i = zero; i < top_half; i++) {
+        cvec[i] = cvec[high_pair];
+        if (high_pair + 1 < size)
+            cvec[i] += cvec[high_pair + 1];
+        high_pair += 2;
+    }
+    assert(high_pair == size || high_pair == size + 1);
+
+    for (int i = top_half; i < size; i++)
+        cvec[i] = Counter();
+
+    max_bucket *= 2;
+    min_bucket *= 2;
+    bucket_size *= 2;
+}
+
+void
+HistStor::grow_convert()
+{
+    int size = cvec.size();
+    int half = (size + 1) / 2; // round up!
+    //bool even = (size & 1) == 0;
+
+    int pair = size - 1;
+    for (int i = size - 1; i >= half; --i) {
+        cvec[i] = cvec[pair];
+        if (pair - 1 >= 0)
+            cvec[i] += cvec[pair - 1];
+        pair -= 2;
+    }
+
+    for (int i = half - 1; i >= 0; i--)
+        cvec[i] = Counter();
+
+    min_bucket = -max_bucket;// - (even ? bucket_size : 0);
+    bucket_size *= 2;
+}
+
+void
+HistStor::grow_up()
+{
+    int size = cvec.size();
+    int half = (size + 1) / 2; // round up!
+
+    int pair = 0;
+    for (int i = 0; i < half; i++) {
+        cvec[i] = cvec[pair];
+        if (pair + 1 < size)
+            cvec[i] += cvec[pair + 1];
+        pair += 2;
+    }
+    assert(pair == size || pair == size + 1);
+
+    for (int i = half; i < size; i++)
+        cvec[i] = Counter();
+
+    max_bucket *= 2;
+    bucket_size *= 2;
+}
+
 Formula::Formula()
 {
 }
diff -r 8bdcec97b36b -r c1e158414648 src/base/statistics.hh
--- a/src/base/statistics.hh    Mon Jan 10 11:11:17 2011 -0800
+++ b/src/base/statistics.hh    Mon Jan 10 11:11:17 2011 -0800
@@ -1435,6 +1435,146 @@
 };
 
 /**
+ * Templatized storage and interface for a histogram stat.
+ */
+class HistStor
+{
+  public:
+    /** The parameters for a distribution stat. */
+    struct Params : public DistParams
+    {
+        /** The number of buckets.. */
+        size_type buckets;
+
+        Params() : DistParams(Hist) {}
+    };
+
+  private:
+    /** The minimum value to track. */
+    Counter min_bucket;
+    /** The maximum value to track. */
+    Counter max_bucket;
+    /** The number of entries in each bucket. */
+    Counter bucket_size;
+
+    /** The current sum. */
+    Counter sum;
+    /** The sum of squares. */
+    Counter squares;
+    /** The number of samples. */
+    Counter samples;
+    /** Counter for each bucket. */
+    VCounter cvec;
+
+  public:
+    HistStor(Info *info)
+        : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
+    {
+        reset(info);
+    }
+
+    void grow_up();
+    void grow_out();
+    void grow_convert();
+
+    /**
+     * Add a value to the distribution for the given number of times.
+     * @param val The value to add.
+     * @param number The number of times to add the value.
+     */
+    void
+    sample(Counter val, int number)
+    {
+        assert(min_bucket < max_bucket);
+        if (val < min_bucket) {
+            if (min_bucket == 0)
+                grow_convert();
+
+            while (val < min_bucket)
+                grow_out();
+        } else if (val >= max_bucket + bucket_size) {
+            if (min_bucket == 0) {
+                while (val >= max_bucket + bucket_size)
+                    grow_up();
+            } else {
+                while (val >= max_bucket + bucket_size)
+                    grow_out();
+            }
+        }
+
+        size_type index =
+            (int64_t)std::floor((val - min_bucket) / bucket_size);
+
+        assert(index >= 0 && index < size());
+        cvec[index] += number;
+
+        sum += val * number;
+        squares += val * val * number;
+        samples += number;
+    }
+
+    /**
+     * Return the number of buckets in this distribution.
+     * @return the number of buckets.
+     */
+    size_type size() const { return cvec.size(); }
+
+    /**
+     * Returns true if any calls to sample have been made.
+     * @return True if any values have been sampled.
+     */
+    bool
+    zero() const
+    {
+        return samples == Counter();
+    }
+
+    void
+    prepare(Info *info, DistData &data)
+    {
+        const Params *params = safe_cast<const Params *>(info->storageParams);
+
+        assert(params->type == Hist);
+        data.type = params->type;
+        data.min = min_bucket;
+        data.max = max_bucket + bucket_size - 1;
+        data.bucket_size = bucket_size;
+
+        data.min_val = min_bucket;
+        data.max_val = max_bucket;
+
+        int buckets = params->buckets;
+        data.cvec.resize(buckets);
+        for (off_type i = 0; i < buckets; ++i)
+            data.cvec[i] = cvec[i];
+
+        data.sum = sum;
+        data.squares = squares;
+        data.samples = samples;
+    }
+
+    /**
+     * Reset stat value to default
+     */
+    void
+    reset(Info *info)
+    {
+        const Params *params = safe_cast<const Params *>(info->storageParams);
+        min_bucket = 0;
+        max_bucket = params->buckets - 1;
+        bucket_size = 1;
+
+        size_type size = cvec.size();
+        for (off_type i = 0; i < size; ++i)
+            cvec[i] = Counter();
+
+        sum = Counter();
+        squares = Counter();
+        samples = Counter();
+    }
+};
+
+/**
  * Templatized storage and interface for a distribution that calculates mean
  * and variance.
  */
@@ -2294,6 +2434,29 @@
 };
 
 /**
+ * A simple histogram stat.
+ * @sa Stat, DistBase, HistStor
+ */
+class Histogram : public DistBase<Histogram, HistStor>
+{
+  public:
+    /**
+     * Set the parameters of this histogram. @sa HistStor::Params
+     * @param size The number of buckets in the histogram
+     * @return A reference to this histogram.
+     */
+    Histogram &
+    init(size_type size)
+    {
+        HistStor::Params *params = new HistStor::Params;
+        params->buckets = size;
+        this->setParams(params);
+        this->doInit();
+        return this->self();
+    }
+};
+
+/**
  * Calculates the mean and variance of all the samples.
  * @sa DistBase, SampleStor
  */
diff -r 8bdcec97b36b -r c1e158414648 src/base/stats/info.hh
--- a/src/base/stats/info.hh    Mon Jan 10 11:11:17 2011 -0800
+++ b/src/base/stats/info.hh    Mon Jan 10 11:11:17 2011 -0800
@@ -164,7 +164,7 @@
     virtual Result total() const = 0;
 };
 
-enum DistType { Deviation, Dist };
+enum DistType { Deviation, Dist, Hist };
 
 struct DistData
 {
diff -r 8bdcec97b36b -r c1e158414648 src/base/stats/text.cc
--- a/src/base/stats/text.cc    Mon Jan 10 11:11:17 2011 -0800
+++ b/src/base/stats/text.cc    Mon Jan 10 11:11:17 2011 -0800
@@ -377,11 +377,11 @@
     size_t size = data.cvec.size();
 
     Result total = 0.0;
-    if (data.underflow != NAN)
+    if (data.type == Dist && data.underflow != NAN)
         total += data.underflow;
     for (off_type i = 0; i < size; ++i)
         total += data.cvec[i];
-    if (data.overflow != NAN)
+    if (data.type == Dist && data.overflow != NAN)
         total += data.overflow;
_______________________________________________
m5-dev mailing list
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to