Stats: Add a sparse histogram stat object.
authorThomas Grass <Thomas.Grass@ARM.com>
Fri, 19 Aug 2011 20:08:05 +0000 (15:08 -0500)
committerThomas Grass <Thomas.Grass@ARM.com>
Fri, 19 Aug 2011 20:08:05 +0000 (15:08 -0500)
src/base/statistics.hh
src/base/stats/info.hh
src/base/stats/output.hh
src/base/stats/text.cc
src/base/stats/text.hh
src/base/stats/types.hh
src/python/swig/stats.i
src/unittest/stattest.cc

index cf8349d246a5659cde69741861fa88e08216ceae..d98c794149f7133e63fe14c33b2298d636260cb1 100644 (file)
@@ -56,6 +56,7 @@
 #include <functional>
 #include <iosfwd>
 #include <list>
+#include <map>
 #include <string>
 #include <vector>
 
@@ -2608,6 +2609,190 @@ class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
     std::string str() const { return this->s.str(); }
 };
 
+template <class Stat>
+class SparseHistInfoProxy : public InfoProxy<Stat, SparseHistInfo>
+{
+  public:
+    SparseHistInfoProxy(Stat &stat) : InfoProxy<Stat, SparseHistInfo>(stat) {}
+};
+
+/**
+ * Implementation of a sparse histogram stat. The storage class is
+ * determined by the Storage template.
+ */
+template <class Derived, class Stor>
+class SparseHistBase : public DataWrap<Derived, SparseHistInfoProxy>
+{
+  public:
+    typedef SparseHistInfoProxy<Derived> Info;
+    typedef Stor Storage;
+    typedef typename Stor::Params Params;
+
+  protected:
+    /** The storage for this stat. */
+    char storage[sizeof(Storage)];
+
+  protected:
+    /**
+     * Retrieve the storage.
+     * @return The storage object for this stat.
+     */
+    Storage *
+    data()
+    {
+        return reinterpret_cast<Storage *>(storage);
+    }
+
+    /**
+     * Retrieve a const pointer to the storage.
+     * @return A const pointer to the storage object for this stat.
+     */
+    const Storage *
+    data() const
+    {
+        return reinterpret_cast<const Storage *>(storage);
+    }
+
+    void
+    doInit()
+    {
+        new (storage) Storage(this->info());
+        this->setInit();
+    }
+
+  public:
+    SparseHistBase() { }
+
+    /**
+     * Add a value to the distribtion n times. Calls sample on the storage
+     * class.
+     * @param v The value to add.
+     * @param n The number of times to add it, defaults to 1.
+     */
+    template <typename U>
+    void sample(const U &v, int n = 1) { data()->sample(v, n); }
+
+    /**
+     * Return the number of entries in this stat.
+     * @return The number of entries.
+     */
+    size_type size() const { return data()->size(); }
+    /**
+     * Return true if no samples have been added.
+     * @return True if there haven't been any samples.
+     */
+    bool zero() const { return data()->zero(); }
+
+    void
+    prepare()
+    {
+        Info *info = this->info();
+        data()->prepare(info, info->data);
+    }
+
+    /**
+     * Reset stat value to default
+     */
+    void
+    reset()
+    {
+        data()->reset(this->info());
+    }
+};
+
+/**
+ * Templatized storage and interface for a sparse histogram stat.
+ */
+class SparseHistStor
+{
+  public:
+    /** The parameters for a sparse histogram stat. */
+    struct Params : public DistParams
+    {
+        Params() : DistParams(Hist) {}
+    };
+
+  private:
+    /** Counter for number of samples */
+    Counter samples;
+    /** Counter for each bucket. */
+    MCounter cmap;
+
+  public:
+    SparseHistStor(Info *info)
+    {
+        reset(info);
+    }
+
+    /**
+     * 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)
+    {
+        cmap[val] += number;
+        samples += number;
+    }
+
+    /**
+     * Return the number of buckets in this distribution.
+     * @return the number of buckets.
+     */
+    size_type size() const { return cmap.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, SparseHistData &data)
+    {
+        MCounter::iterator it;
+        data.cmap.clear();
+        for (it = cmap.begin(); it != cmap.end(); it++) {
+            data.cmap[(*it).first] = (*it).second;
+        }
+
+        data.samples = samples;
+    }
+
+    /**
+     * Reset stat value to default
+     */
+    void
+    reset(Info *info)
+    {
+        cmap.clear();
+        samples = 0;
+    }
+};
+
+class SparseHistogram : public SparseHistBase<SparseHistogram, SparseHistStor>
+{
+  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.
+     */
+    SparseHistogram &
+    init(size_type size)
+    {
+        SparseHistStor::Params *params = new SparseHistStor::Params;
+        this->setParams(params);
+        this->doInit();
+        return this->self();
+    }
+};
+
 class Temp;
 /**
  * A formula for statistics that is calculated when printed. A formula is
index fa7c8cc3d0700b6555ad403d5bc9cae362fe064d..2c5b44a38095f4b0500c53b39061d014e45874a1 100644 (file)
@@ -234,6 +234,20 @@ class FormulaInfo : public VectorInfo
     virtual std::string str() const = 0;
 };
 
+/** Data structure of sparse histogram */
+struct SparseHistData
+{
+    MCounter cmap;
+    Counter samples;
+};
+
+
+class SparseHistInfo : public Info
+{
+  public:
+    /** Local storage for the entry values, used for printing. */
+    SparseHistData data;
+};
 
 } // namespace Stats
 
index 26c4c5bbd345fd82a73e148abfdb8f969fe04d84..9cd33a5f963bd5fb7a3826a6fead4ea8da2bc781 100644 (file)
@@ -43,6 +43,7 @@ class DistInfo;
 class VectorDistInfo;
 class Vector2dInfo;
 class FormulaInfo;
+class SparseHistInfo; // Sparse histogram
 
 struct Output
 {
@@ -57,6 +58,7 @@ struct Output
     virtual void visit(const VectorDistInfo &info) = 0;
     virtual void visit(const Vector2dInfo &info) = 0;
     virtual void visit(const FormulaInfo &info) = 0;
+    virtual void visit(const SparseHistInfo &info) = 0; // Sparse histogram
 };
 
 } // namespace Stats
index 45d59ff29f1cba7f0ad4d6ea437ca21e9695d460..f8471f1a11de0310300f901a9e11c3db758cd547 100644 (file)
@@ -581,6 +581,92 @@ Text::visit(const FormulaInfo &info)
     visit((const VectorInfo &)info);
 }
 
+/*
+  This struct implements the output methods for the sparse
+  histogram stat
+*/
+struct SparseHistPrint
+{
+    string name;
+    string separatorString;
+    string desc;
+    Flags flags;
+    bool descriptions;
+    int precision;
+
+    const SparseHistData &data;
+
+    SparseHistPrint(const Text *text, const SparseHistInfo &info);
+    void init(const Text *text, const Info &info);
+    void operator()(ostream &stream) const;
+};
+
+/* Call initialization function */
+SparseHistPrint::SparseHistPrint(const Text *text, const SparseHistInfo &info)
+    : data(info.data)
+{
+    init(text, info);
+}
+
+/* Initialization function */
+void
+SparseHistPrint::init(const Text *text, const Info &info)
+{
+    name = info.name;
+    separatorString = info.separatorString;
+    desc = info.desc;
+    flags = info.flags;
+    precision = info.precision;
+    descriptions = text->descriptions;
+}
+
+/* Grab data from map and write to output stream */
+void
+SparseHistPrint::operator()(ostream &stream) const
+{
+    string base = name + separatorString;
+
+    ScalarPrint print;
+    print.precision = precision;
+    print.flags = flags;
+    print.descriptions = descriptions;
+    print.desc = desc;
+    print.pdf = NAN;
+    print.cdf = NAN;
+
+    print.name = base + "samples";
+    print.value = data.samples;
+    print(stream);
+
+    MCounter::const_iterator it;
+    for (it = data.cmap.begin(); it != data.cmap.end(); it++) {
+        stringstream namestr;
+        namestr << base;
+
+        namestr <<(*it).first;
+        print.name = namestr.str();
+        print.value = (*it).second;
+        print(stream);
+    }
+
+    print.pdf = NAN;
+    print.cdf = NAN;
+
+    print.name = base + "total";
+    print.value = total;
+    print(stream);
+}
+
+void
+Text::visit(const SparseHistInfo &info)
+{
+    if (noOutput(info))
+        return;
+
+    SparseHistPrint print(this, info);
+    print(*stream);
+}
+
 Output *
 initText(const string &filename, bool desc)
 {
index 24abaac97b6e08159e330cdf735ee4ed20d07b2a..7f7edaa91393712f95a24161181b65c6fdb17cd7 100644 (file)
@@ -67,6 +67,7 @@ class Text : public Output
     virtual void visit(const VectorDistInfo &info);
     virtual void visit(const Vector2dInfo &info);
     virtual void visit(const FormulaInfo &info);
+    virtual void visit(const SparseHistInfo &info);
 
     // Implement Output
     virtual bool valid() const;
index 9faa8d33d0a84d216cdf006360db678e1d4d4bd4..831cc6db5bc5dabe133de090ad98e9e2144a57a1 100644 (file)
@@ -32,6 +32,7 @@
 #define __BASE_STATS_TYPES_HH__
 
 #include <limits>
+#include <map>
 #include <vector>
 
 #include "base/types.hh"
@@ -42,6 +43,8 @@ namespace Stats {
 typedef double Counter;
 /** vector of counters. */
 typedef std::vector<Counter> VCounter;
+/** map of counters */
+typedef std::map<Counter, int> MCounter;
 
 typedef std::numeric_limits<Counter> CounterLimits;
 
index 0213d5c01389ce2c8fe5c96bb85811da2de87ae7..87810d305887195172953a4161b9d26848e6547a 100644 (file)
@@ -137,6 +137,7 @@ template <class T> T cast_info(Info *info);
 %template(dynamic_VectorDistInfo) cast_info<VectorDistInfo *>;
 %template(dynamic_Vector2dInfo) cast_info<Vector2dInfo *>;
 %template(dynamic_FormulaInfo) cast_info<FormulaInfo *>;
+%template(dynamic_SparseHistInfo) cast_info<SparseHistInfo *>;
 
 void initSimStats();
 Output *initText(const std::string &filename, bool desc);
index c5e39888d87970b1e1a15b34a7db49273e026fdc..ccce2173b7d26245927395ce8a691f586925a336 100644 (file)
@@ -92,6 +92,7 @@ struct StatTest
     Histogram h10;
     Histogram h11;
     Histogram h12;
+    SparseHistogram sh1;
 
     Formula f1;
     Formula f2;
@@ -316,6 +317,12 @@ StatTest::init()
         .desc("this is histogram 12")
         ;
 
+    sh1
+        .init(0)
+        .name("SparseHistogram1")
+        .desc("this is sparse histogram 1")
+        ;
+
     f1
         .name("Formula1")
         .desc("this is formula 1")
@@ -623,4 +630,8 @@ StatTest::run()
         h11.sample(i);
         h12.sample(i);
     }
+
+    for (int i = 0; i < 1000; i++) {
+        sh1.sample(random() % 10000);
+    }
 }