Stats: Add a sparse histogram stat object.

This commit is contained in:
Thomas Grass
2011-08-19 15:08:05 -05:00
parent 676a530b77
commit 3f1ae35c6d
8 changed files with 303 additions and 0 deletions

View 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

View 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

View 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

View 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)
{

View 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;

View 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;

View 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);

View 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);
}
}