statistics.hh
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 2,775 行 · 第 1/5 页
HH
2,775 行
return false; return true; } bool check() const { return storage != NULL; } void reset() { for (int i = 0; i < size(); ++i) data(i)->reset(); } public: VectorBase() : storage(NULL) {} ~VectorBase() { if (!storage) return; for (int i = 0; i < _size; ++i) data(i)->~Storage(); delete [] reinterpret_cast<char *>(storage); } /** * Return a reference (ScalarProxy) to the stat at the given index. * @param index The vector index to access. * @return A reference of the stat. */ Proxy operator[](int index) { assert (index >= 0 && index < size()); return Proxy(this, index); } void update(StatData *data) {}};template <class Stat>class VectorProxy{ private: Stat *stat; int offset; int len; private: mutable VResult vec; typename Stat::Storage * data(int index) { assert(index < len); return stat->data(offset + index); } const typename Stat::Storage * data(int index) const { assert(index < len); return const_cast<Stat *>(stat)->data(offset + index); } public: const VResult & result() const { vec.resize(size()); for (int i = 0; i < size(); ++i) vec[i] = data(i)->result(stat->params); return vec; } Result total() const { Result total = 0; for (int i = 0; i < size(); ++i) total += data(i)->result(stat->params); return total; } public: VectorProxy(Stat *s, int o, int l) : stat(s), offset(o), len(l) { } VectorProxy(const VectorProxy &sp) : stat(sp.stat), offset(sp.offset), len(sp.len) { } const VectorProxy & operator=(const VectorProxy &sp) { stat = sp.stat; offset = sp.offset; len = sp.len; return *this; } ScalarProxy<Stat> operator[](int index) { assert (index >= 0 && index < size()); return ScalarProxy<Stat>(stat, offset + index); } size_t size() const { return len; } /** * This stat has no state. Nothing to reset. */ void reset() { }};template <class Stor>class Vector2dBase : public DataAccess{ public: typedef Stor Storage; typedef typename Storage::Params Params; typedef VectorProxy<Vector2dBase<Storage> > Proxy; friend class ScalarProxy<Vector2dBase<Storage> >; friend class VectorProxy<Vector2dBase<Storage> >; protected: size_t x; size_t y; size_t _size; Storage *storage; Params params; protected: Storage *data(int index) { return &storage[index]; } const Storage *data(int index) const { return &storage[index]; } void doInit(int _x, int _y) { assert(_x > 0 && _y > 0 && "sizes must be positive!"); assert(!storage && "already initialized"); Vector2dData *statdata = dynamic_cast<Vector2dData *>(find()); x = _x; y = _y; statdata->x = _x; statdata->y = _y; _size = x * y; char *ptr = new char[_size * sizeof(Storage)]; storage = reinterpret_cast<Storage *>(ptr); for (int i = 0; i < _size; ++i) new (&storage[i]) Storage(params); setInit(); } public: Vector2dBase() : storage(NULL) {} ~Vector2dBase() { if (!storage) return; for (int i = 0; i < _size; ++i) data(i)->~Storage(); delete [] reinterpret_cast<char *>(storage); } void update(Vector2dData *newdata) { int size = this->size(); newdata->cvec.resize(size); for (int i = 0; i < size; ++i) newdata->cvec[i] = data(i)->value(params); } std::string ysubname(int i) const { return (*this->y_subnames)[i]; } Proxy operator[](int index) { int offset = index * y; assert (index >= 0 && offset + index < size()); return Proxy(this, offset, y); } size_t size() const { return _size; } bool zero() const { return data(0)->zero();#if 0 for (int i = 0; i < size(); ++i) if (!data(i)->zero()) return false; return true;#endif } /** * Reset stat value to default */ void reset() { for (int i = 0; i < size(); ++i) data(i)->reset(); } bool check() { return storage != NULL; }};////////////////////////////////////////////////////////////////////////// Non formula statistics/////////////////////////////////////////////////////////////////////////** * Templatized storage and interface for a distrbution stat. */struct DistStor{ public: /** The parameters for a distribution stat. */ struct Params { /** The minimum value to track. */ Counter min; /** The maximum value to track. */ Counter max; /** The number of entries in each bucket. */ Counter bucket_size; /** The number of buckets. Equal to (max-min)/bucket_size. */ int size; }; enum { fancy = false }; private: /** The smallest value sampled. */ Counter min_val; /** The largest value sampled. */ Counter max_val; /** The number of values sampled less than min. */ Counter underflow; /** The number of values sampled more than max. */ Counter overflow; /** The current sum. */ Counter sum; /** The sum of squares. */ Counter squares; /** The number of samples. */ Counter samples; /** Counter for each bucket. */ VCounter cvec; public: DistStor(const Params ¶ms) : cvec(params.size) { reset(); } /** * 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. * @param params The paramters of the distribution. */ void sample(Counter val, int number, const Params ¶ms) { if (val < params.min) underflow += number; else if (val > params.max) overflow += number; else { int index = (int)std::floor((val - params.min) / params.bucket_size); assert(index < size(params)); cvec[index] += number; } if (val < min_val) min_val = val; if (val > max_val) max_val = val; Counter sample = val * number; sum += sample; squares += sample * sample; samples += number; } /** * Return the number of buckets in this distribution. * @return the number of buckets. * @todo Is it faster to return the size from the parameters? */ size_t size(const Params &) const { return cvec.size(); } /** * Returns true if any calls to sample have been made. * @param params The paramters of the distribution. * @return True if any values have been sampled. */ bool zero(const Params ¶ms) const { return samples == Counter(); } void update(DistDataData *data, const Params ¶ms) { data->min = params.min; data->max = params.max; data->bucket_size = params.bucket_size; data->size = params.size; data->min_val = (min_val == INT_MAX) ? 0 : min_val; data->max_val = (max_val == INT_MIN) ? 0 : max_val; data->underflow = underflow; data->overflow = overflow; data->cvec.resize(params.size); for (int i = 0; i < params.size; ++i) data->cvec[i] = cvec[i]; data->sum = sum; data->squares = squares; data->samples = samples; } /** * Reset stat value to default */ void reset() { min_val = INT_MAX; max_val = INT_MIN; underflow = 0; overflow = 0; int size = cvec.size(); for (int 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. */struct FancyStor{ public: /** * No paramters for this storage. */ struct Params {}; enum { fancy = true }; private: /** The current sum. */ Counter sum; /** The sum of squares. */ Counter squares; /** The number of samples. */ Counter samples; public: /** * Create and initialize this storage. */ FancyStor(const Params &) : sum(Counter()), squares(Counter()), samples(Counter()) { } /** * Add a value the given number of times to this running average. * Update the running sum and sum of squares, increment the number of * values seen by the given number. * @param val The value to add. * @param number The number of times to add the value. * @param p The parameters of this stat. */ void sample(Counter val, int number, const Params &p) { Counter value = val * number; sum += value; squares += value * value; samples += number; } void update(DistDataData *data, const Params ¶ms) { data->sum = sum; data->squares = squares; data->samples = samples; } /** * Return the number of entries in this stat, 1 * @return 1. */ size_t size(const Params &) const { return 1; } /** * Return true if no samples have been added. * @return True if no samples have been added. */ bool zero(const Params &) const { return samples == Counter(); } /** * Reset stat value to default */ void reset() { sum = Counter(); squares = Counter(); samples = Counter(); }};/** * Templatized storage for distribution that calculates per tick mean and * variance. */struct AvgFancy{ public: /** No parameters for this storage. */ struct Params {}; enum { fancy = true }; private: /** Current total. */ Counter sum; /** Current sum of squares. */ Counter squares; public: /** * Create and initialize this storage. */ AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {} /** * Add a value to the distribution for the given number of times. * Update the running sum and sum of squares. * @param val The value to add. * @param number The number of times to add the value. * @param p The paramters of the distribution. */ void sample(Counter val, int number, const Params &p) { Counter value = val * number; sum += value; squares += value * value; } void update(DistDataData *data, const Params ¶ms) { data->sum = sum; data->squares = squares; data->samples = curTick; } /** * Return the number of entries, in this case 1. * @return 1. */ size_t size(const Params ¶ms) const { return 1; } /** * Return true if no samples have been added. * @return True if the sum is zero. */ bool zero(const Params ¶ms) const { return sum == Counter(); } /** * Reset stat value to default */ void reset() { sum = Counter(); squares = Counter(); }};/** * Implementation of a distribution stat. The type of distribution is * determined by the Storage template. @sa ScalarBase */template <class Stor>class DistBase : public DataAccess{ public: typedef Stor Storage; /** Define the params of the storage class. */ typedef typename Storage::Params Params; protected: /** The storage for this stat. */ char storage[sizeof(Storage)] __attribute__ ((aligned (8))); /** The parameters for this stat. */ Params params; 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);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?