Stats: Add a sparse histogram stat object.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user