1. gem5 的统计包
当前统计包的设计理念是拥有一个名为 Stat 的单一基类,该类仅仅是通往统计值其他所有重要方面的一个接口。因此,这个 Stat 基类包含虚函数,用于为所有统计值命名、设置精度、设置标志以及初始化大小。对于所有基于向量的统计,在使用统计之前进行初始化非常重要,以便进行适当的存储分配。对于所有其他统计,命名和标志设置也很重要,但对于二进制文件的正常执行而言,其重要性不如前者。在代码中,这是通过一个 regStats() 流程来实现的,在该流程中,所有统计都可以在统计数据库中进行注册和初始化。
因此,要添加您自己的统计,只需将它们添加到相应类的数据成员列表中,并确保在该类的 regStats 函数中对它们进行初始化/注册。
以下是各种初始化函数的列表。请注意,所有这些函数都返回一个 Stat& 引用,从而提供了一种简洁的调用方式。
-
init(各种参数)// 对于不同类型的统计,此函数有所不同。-
Average: 没有init() -
Vector:init(size_t)// 表示向量的大小 -
AverageVector:init(size_t)// 表示向量的大小 -
Vector2d:init(size_t x, size_t y)// 行数, 列数 -
Distribution:init(min, max, bkt)// min 指最小值,max 指最大值,bkt 指桶的大小。换句话说,如果您设置 min=0, max=15, bkt=8,那么 0-7 将进入桶 0,8-15 将进入桶 1。 -
StandardDeviation: 没有init() -
AverageDeviation: 没有init() -
VectorDistribution:init(size, min, max, bkt)// size 指向量的大小,其余参数与 Distributions 相同。 -
VectorStandardDeviation:init(size)// size 指向量的大小 -
VectorAverageDeviation:init(size)// size 指向量的大小 -
Formula: 没有init()
-
-
name(const std::string name)// 统计的名称 -
desc(const std::string desc)// 统计的简要描述 -
precision(int p)// p 指小数点后保留的位数。p=0 将强制四舍五入为整数。 -
prereq(const Stat &prereq)// 这表示除非 prereq 统计具有非零值,否则不应打印此统计。(例如,如果缓存访问次数为 0,则不打印缓存未命中、命中等统计信息) -
subname(int index, const std::string subname)// 这用于基于向量的统计,为向量的每个索引指定一个子名称。 -
subdesc(int index, const std::string subname)// 同样用于基于向量的统计,为每个索引指定一个子描述。对于 2D 向量,子名称应用于每个行(x 方向)。可以使用 Vector2d 的成员函数ysubname来命名 y 方向,详见代码。 -
flags(FormatFlags f)// 这些是可以传递给统计的各种标志,下面将进行描述。-
none-- 无特殊格式 -
total-- 这用于基于向量的统计,如果设置此标志,将在最后打印向量的总和(对于支持此操作的统计)。 -
pdf-- 这将打印统计的概率分布 -
nozero-- 如果统计值为零,则不打印 -
nonan-- 如果统计值不是数字,则不打印 -
cdf-- 这将打印统计的累积分布
-
以下是如何初始化一个 VectorDistribution 的示例:
cpp
vector_dist.init(4,0,5,2)
.name("Dummy Vector Dist")
.desc("there are 4 distributions with buckets 0-1, 2-3, 4-5")
.flags(nonan | pdf)
;
统计类型
标量
最基本的统计是 Scalar。它体现了基本的计数统计。这是一个模板化的统计,接受两个参数:一个类型和一个 bin。默认类型是 Counter,默认 bin 是 NoBin(即此统计没有分桶)。其用法很简单:要为其赋值,只需写 foo = 10;,或者要递增它,只需像对任何其他类型一样使用 ++ 或 +=。
平均值
这是一个"特殊用途"的统计,旨在计算模拟周期内某事物的平均值。通过示例可以最好地解释此统计。如果您想知道模拟过程中负载存储队列的平均占用率,您需要每个周期累积 LSQ 中的指令数,最后将其除以周期数。对于此统计,可能有很多周期 LSQ 占用率没有变化。因此,您可以使用此统计,您只需要在 LSQ 占用率发生变化时显式更新统计即可。统计本身将处理没有变化的周期。此统计可以进行分桶,并且其模板化方式与 Stat 相同。
向量
Vector 正如其名,是模板参数中类型 T 的向量。它也可以进行分桶。Vector 最自然的用法是类似于跟踪 SMT 线程数上的某些统计。可以通过声明 Vector<> foo; 然后稍后将大小初始化为 n 来创建大小为 n 的 Vector。此时,可以像访问常规向量或数组一样访问 foo,例如 foo[7]++。
平均值向量
AverageVector 只是一个 Average 的向量。
二维向量
Vector2d 是一个二维向量。它可以在 x 和 y 两个方向上命名,尽管主名称是在 x 维度上给出的。要在 y 维度上命名,请使用仅适用于 Vector2d 的特殊函数 ysubname。
分布
这本质上是一个向量,但略有不同。在 Vector 中,索引映射到该桶所关注的项,而在 Distribution 中,您可以将所关注的不同范围映射到一个桶。基本上,如果您将 Distribution 的 init 函数的 bkt 参数设置为 1,您不妨使用 Vector。
标准差
此统计计算模拟周期数的标准差。它与 Average 类似,其内部内置了行为,但需要每个周期都更新。
平均偏差
此统计也计算标准差,但它不需要像 Average 那样每个周期都更新。它将自行处理没有变化的周期。
向量分布
这只是一个分布的向量。
向量标准差
这只是一个标准差的向量。
向量平均偏差
这只是一个 AverageDeviation 的向量。
直方图
此统计将每个采样值放入可配置数量的桶中的一个桶。所有桶形成一个连续区间且长度相等。如果存在无法放入任何现有桶的采样值,则桶的长度会动态扩展。
稀疏直方图
此统计与直方图类似,不同之处在于它只能对自然数进行采样。例如,SparseHistogram 适用于计算内存地址的访问次数。
公式
这是一个 Formula 统计。这适用于任何在模拟结束时需要计算的情况,例如某种比率。因此,定义 Formula 的示例如下:
cpp
Formula foo = bar + 10 / num;
Formula 有一些微妙之处。如果 bar 和 num 都是统计(包括 Formula 类型),则没有问题。如果 bar 或 num 是常规变量,则必须使用 constant(bar) 来限定。这本质上是一种转换。如果您想在定义时使用 bar 或 num 的值,请使用 constant()。如果您想在公式计算时(即结束时)使用 bar 或 num 的值,请将 num 定义为 Scalar。如果 num 是 Vector,请在公式中使用 sum(num) 计算其总和。操作 scalar(num)(将常规变量转换为 Scalar)已不存在。
2. 统计 API
内容
-
通用统计函数
-
Stats::Group - 统计容器
-
统计标志
-
统计类
-
附录:迁移至新的统计跟踪风格
通用统计函数
| 函数签名 | 描述 |
|---|---|
void Stats::dump() |
将所有统计信息转储到已注册的输出,例如 stats.txt。 |
void Stats::reset() |
重置统计信息。 |
Stats::Group - 统计容器
通常,统计对象可以作为类变量放在任何 SimObject 中。然而,最近的一次更新解决了 gem5 中 SimObject 的层次结构特性,这反过来使得对象的统计信息也具有层次结构。该更新引入了 Stats::Group 类,它是一个统计容器,并且知晓 SimObject 的层次结构。理想情况下,此容器应包含 SimObject 中的所有统计信息。
注意 :如果您决定在 SimObject 中使用 Stats::Group 结构,通常有两种方法:
-
使用
Stats::Group(Stats::Group &parent, const std::string &name)构造函数创建一个子组。当希望拥有相同统计结构的多个实例时,这非常有用。 -
使用
Stats::Group(Stats::Group &parent)构造函数,该构造函数将当前组的统计信息合并(即添加)到父组中。因此,添加到当前组的统计信息的行为就像它们被添加到父组一样。
Stats::Group 宏
#define ADD_STAT(n, ...) n(this, # n, __VA_ARGS__)
用于向统计组添加统计信息的便捷宏。
此宏用于在 Group 构造函数的初始化列表中向 Stats::Group 添加统计信息。该宏会自动将统计信息分配给当前组,并赋予其与类中相同的名称。例如:
cpp
struct MyStats : public Stats::Group
{
Stats::Scalar scalar0;
Stats::Scalar scalar1;
MyStats(Stats::Group *parent)
: Stats::Group(parent),
ADD_STAT(scalar0, "Description of scalar0"), // 等价于 scalar0(this, "scalar0", "Description of scalar0"),其中 scalar0 具有以下构造函数
// Stats::Scalar(Group *parent = nullptr, const char *name = nullptr, const char *desc = nullptr)
ADD_STAT(scalar1, "Description of scalar1") // 等价于 scalar1(this, "scalar1", "Description of scalar1")
{
// 如果需要,可以在这里进行额外的初始化(例如设置直方图的桶数)
// scalar0.init(10);
}
};
Stats::Group 函数
-
Group(Group *parent, const char *name = nullptr)构造一个新的统计组。
构造函数接受两个参数:一个父组和一个名称。通常应指定父组。但是,在特殊情况下,父组可能为空。一种特殊情况是 SimObjects,其 Python 代码执行组父级的后期绑定。
如果
name参数为 NULL,则该组将合并到父组中,而不是创建子组。属于合并组的统计信息的行为就像它们已直接添加到父组一样。 -
virtual void regStats()设置统计参数的回调函数。
此回调通常用于需要除名称和描述之外参数的复杂统计信息(例如,分布)。对于无法在构造函数中初始化的统计对象(例如跟踪总线主设备的统计信息,这些主设备只有在整个系统实例化后才能被发现),可以使用此回调。统计名称和描述通常应使用
ADD_STAT宏在构造函数中设置。 -
virtual void resetStats()重置统计信息的回调函数。
-
virtual void preDumpStats()在统计信息转储之前的回调函数。对于需要在统计框架实现的功能之外执行计算的对象,可以重写此方法。
-
void addStat(Stats::Info *info)向此组注册一个统计信息。此方法通常在统计信息实例化时自动调用。
-
const std::map<std::string, Group *> &getStatGroups() const获取与此对象关联的所有子组。
-
const std::vector<Info *> &getStats() const获取与此对象关联的所有统计信息。
-
void addStatGroup(const char *name, Group *block)将一个统计块添加为此块的子块。
此方法只能从 Group 构造函数或
regStats中调用。通常仅在从 Python 设置 SimObject 层次结构时显式调用。 -
const Info * resolveStat(std::string name) const在此组内通过名称解析统计信息。
此方法遍历此组和子组中的统计信息,并返回与提供名称匹配的统计信息的指针。输入名称必须相对于此组的名称。
例如,如果此组是 SimObject
system.bigCluster.cpus,并且我们想要统计信息system.bigCluster.cpus.ipc,则输入参数应为字符串"ipc"。
统计标志
| 标志 | 描述 |
|---|---|
Stats::none |
无需额外打印。 |
Stats::total |
打印总和。 |
Stats::pdf |
打印此条目占总量的百分比。 |
Stats::cdf |
打印到此条目为止的累计百分比。 |
Stats::dist |
打印分布。 |
Stats::nozero |
如果此项为零,则不打印。 |
Stats::nonan |
如果此项为 NAN,则不打印。 |
Stats::oneline |
在一行上打印所有值。仅对直方图有用。 |
注意 :尽管标志 Stats::init 和 Stats::display 可用,但不允许用户设置这些标志。
统计类
| 类名 | 描述 |
|---|---|
Stats::Scalar |
简单标量统计。 |
Stats::Average |
计算值的每周期平均值的统计量。 |
Stats::Value |
类似于 Stats::Scalar。 |
Stats::Vector |
标量统计的向量。 |
Stats::AverageVector |
平均值统计的向量。 |
Stats::Vector2d |
标量统计的二维向量。 |
Stats::Distribution |
简单分布统计(具有方便的 min、max、sum 等)。 |
Stats::Histogram |
简单直方图统计(记录等分连续范围的频率)。 |
Stats::SparseHistogram |
记录离散值集合的频率/直方图。 |
Stats::StandardDeviation |
计算所有样本的均值和方差。 |
Stats::AverageDeviation |
计算样本的每周期均值和方差。 |
Stats::VectorDistribution |
分布的向量。 |
Stats::VectorStandardDeviation |
标准差统计的向量。 |
Stats::VectorAverageDeviation |
平均偏差统计的向量。 |
Stats::Formula |
保存涉及多个统计对象算术运算的统计量。 |
注意 :Stats::Average 仅计算标量在模拟周期数上的平均值。要获取量 A 相对于量 B 的平均值,可以利用 Stats::Formula。例如,
cpp
Stats::Scalar totalReadLatency;
Stats::Scalar numReads;
Stats::Formula averageReadLatency = totalReadLatency / numReads;
通用统计函数
以下函数适用于大多数统计类(StatClass 代表如 Scalar, Vector 等),并返回统计对象的引用以支持链式调用。
| 函数签名 | 描述 |
|---|---|
StatClass name(const std::string &name) |
设置统计名称,标记该统计信息需要被打印。 |
StatClass desc(const std::string &_desc) |
设置统计信息的描述。 |
StatClass precision(int _precision) |
设置统计信息的精度(小数点后位数)。 |
StatClass flags(Flags _flags) |
设置标志。 |
StatClass prereq(const Stat &prereq) |
设置先决条件统计信息(仅当此统计信息非零时才打印)。 |
Stats::Scalar
存储有符号整数统计量。
| 函数签名 | 描述 |
|---|---|
void operator++() |
统计量加 1 // 前缀 ++,例如 ++scalar |
void operator--() |
统计量减 1 // 前缀 -- |
void operator++(int) |
统计量加 1 // 后缀 ++,例如 scalar++ |
void operator--(int) |
统计量减 1 // 后缀 -- |
template <typename U> void operator=(const U &v) |
将标量设置为给定值 |
template <typename U> void operator+=(const U &v) |
统计量增加给定值 |
template <typename U> void operator-=(const U &v) |
统计量减少给定值 |
size_type size() |
返回 1 |
Counter value() |
以整数形式返回统计量的当前值 |
Counter value() const |
以整数形式返回统计量的当前值(常量版本) |
Result result() |
以双精度浮点数形式返回统计量的当前值 |
Result total() |
以双精度浮点数形式返回统计量的当前值(总和) |
bool zero() |
如果统计量等于零则返回 true,否则返回 false |
void reset() |
将统计量重置为 0 |
Stats::Average
存储一个整数量(假设为 A)在模拟周期数上的平均值。量 A 在其最近一次更新之后和下一次更新之前的所有周期内保持相同的值。
注意 :当用户调用 Stats::reset() 时,模拟周期数会被重置。
| 函数签名 | 描述 |
|---|---|
void set(Counter val) |
将量 A 设置为给定值 |
void inc(Counter val) |
将量 A 增加给定值 |
void dec(Counter val) |
将量 A 减少给定值 |
Counter value() |
以整数形式返回 A 的当前值 |
Result result() |
以双精度浮点数形式返回当前平均值 |
bool zero() |
如果平均值等于零则返回 true,否则返回 false |
void reset(Info *info) |
保持 A 的当前值,不计算当前周期前的 A 值 |
Stats::Value
存储一个有符号整数统计量,该统计量可以是一个整数,也可以是调用函数或对象方法的结果。
| 函数签名 | 描述 |
|---|---|
Counter value() |
以整数形式返回值 |
Result result() const |
以双精度浮点数形式返回值 |
Result total() const |
以双精度浮点数形式返回值(总和) |
size_type size() const |
返回 1 |
bool zero() const |
如果值为零则返回 true,否则返回 false |
Stats::Vector
存储一个标量统计的数组,其中向量的每个元素都具有与 Stats::Scalar 相似的函数签名。
| 函数签名 | 描述 |
|---|---|
Derived & init(size_type size) |
将向量初始化为给定大小(如果尝试调整已初始化向量的大小则会抛出错误) |
Derived & subname(off_type index, const std::string &name) |
为给定索引处的统计信息添加名称 |
Derived & subdesc(off_type index, const std::string &desc) |
为给定索引处的统计信息添加描述 |
void value(VCounter &vec) const |
将统计信息向量复制到给定的整数向量中 |
void result(VResult &vec) const |
将统计信息向量复制到给定的双精度浮点数向量中 |
Result total() const |
以双精度浮点数形式返回向量中所有统计信息的总和 |
size_type size() const |
返回向量的大小 |
bool zero() const |
如果向量中的每个统计信息都为 0 则返回 true,否则返回 false |
operator[](off_type index) |
获取给定索引处统计信息的引用,例如 vecStats[1] += 9 |
Stats::AverageVector
存储一个平均值统计的数组,其中向量的每个元素都具有与 Stats::Average 相似的函数签名。
| 函数签名 | 描述 |
|---|---|
Derived & init(size_type size) |
将向量初始化为给定大小(如果尝试调整已初始化向量的大小则会抛出错误) |
Derived & subname(off_type index, const std::string &name) |
为给定索引处的统计信息添加名称 |
Derived & subdesc(off_type index, const std::string &desc) |
为给定索引处的统计信息添加描述 |
void value(VCounter &vec) const |
将统计信息向量复制到给定的整数向量中 |
void result(VResult &vec) const |
将统计信息向量复制到给定的双精度浮点数向量中 |
Result total() const |
以双精度浮点数形式返回向量中所有统计信息的总和 |
size_type size() const |
返回向量的大小 |
bool zero() const |
如果向量中的每个统计信息都为 0 则返回 true,否则返回 false |
operator[](off_type index) |
获取给定索引处统计信息的引用,例如 avgStats[1].set(9) |
Stats::Vector2d
存储一个标量统计的二维数组,其中数组的每个元素都具有与 Stats::Scalar 相似的函数签名。此数据结构假定具有相同第二维索引的所有元素具有相同的名称。
| 函数签名 | 描述 |
|---|---|
Derived & init(size_type _x, size_type _y) |
将向量初始化为给定大小(如果尝试调整已初始化向量的大小则会抛出错误) |
Derived & ysubname(off_type index, const std::string &subname) |
将 subname 设置为第二维索引为 index 的元素的统计信息名称 |
Derived & ysubnames(const char **names) |
与上面的 ysubname() 类似,但为第二维的所有索引设置名称 |
std::string ysubname(off_type i) const |
返回第二维索引为 i 的元素的统计信息名称 |
size_type size() const |
返回数组中的元素数量 |
bool zero() |
如果第 0 行第 0 列的元素等于 0 则返回 true,否则返回 false |
Result total() |
以双精度浮点数形式返回所有元素的总和 |
void reset() |
将数组中的每个元素设置为 0 |
operator[](off_type index) |
获取给定索引处统计信息的引用,例如 vecStats[1][2] += 9 |
Stats::Distribution
存储一个量的分布。该分布的统计信息包括:
-
被采样的最小/最大值
-
小于指定最小值或大于指定最大值的值的数量
-
所有样本的总和
-
样本的均值、几何均值和标准差
-
在
[min, max]范围内的直方图,被分割成(max-min)/bucket_size个相同大小的桶,其中min/max/bucket_size是init()函数的输入。
| 函数签名 | 描述 |
|---|---|
Distribution & init(Counter min, Counter max, Counter bkt) |
初始化分布,其中 min 是分布直方图跟踪的最小值,max 是分布直方图跟踪的最大值,bkt 是每个桶中的值的数量 |
void sample(Counter val, int number) |
将 val 添加到分布中 number 次 |
size_type size() const |
返回分布中的桶数 |
bool zero() const |
如果样本数为零则返回 true,否则返回 false |
void reset(Info *info) |
丢弃所有样本 |
add(DistBase &) |
从另一个具有 DistBase 的 Stats 类(例如 Stats::Histogram)合并样本 |
Stats::Histogram
存储一个给定桶数的量的直方图。所有桶的大小相等。与 Stats::Distribution 的直方图(跟踪特定范围内的样本)不同,Stats::Histogram 在其直方图中跟踪所有样本。同时,Stats::Distribution 的参数是一个桶中的值的数量,而 Stats::Histogram 的唯一参数是桶的数量。当新样本超出当前所有桶的范围时,桶将被调整大小。大致上,两个连续的桶将被合并,直到新样本位于其中一个桶内。
除了直方图本身,分布的统计信息还包括:
-
被采样的最小/最大值
-
所有样本的总和
-
样本的均值、几何均值和标准差
| 函数签名 | 描述 |
|---|---|
Histogram & init(size_type size) |
初始化直方图,将桶的数量设置为 size |
void sample(Counter val, int number) |
将 val 添加到直方图中 number 次 |
void add(HistStor *) |
将另一个直方图合并到此直方图 |
size_type size() const |
返回桶的数量 |
bool zero() const |
如果样本数为零则返回 true,否则返回 false |
void reset(Info *info) |
丢弃所有样本 |
Stats::SparseHistogram
存储一组整数值的量的直方图。
| 函数签名 | 描述 |
|---|---|
template <typename U> void sample(const U &v, int n = 1) |
将 v 添加到直方图中 n 次 |
size_type size() const |
返回条目数 |
bool zero() const |
如果样本数为零则返回 true,否则返回 false |
void reset() |
丢弃所有样本 |
Stats::StandardDeviation
跟踪样本的标准差。
| 函数签名 | 描述 |
|---|---|
void sample(Counter val, int number) |
将 val 添加到分布中 number 次 |
size_type size() const |
返回 1 |
bool zero() const |
如果样本数为零则返回 true,否则返回 false |
void reset(Info *info) |
丢弃所有样本 |
add(DistBase &) |
从另一个具有 DistBase 的 Stats 类(例如 Stats::Distribution)合并样本 |
Stats::AverageDeviation
跟踪样本的平均偏差。
| 函数签名 | 描述 |
|---|---|
void sample(Counter val, int number) |
将 val 添加到分布中 number 次 |
size_type size() const |
返回 1 |
bool zero() const |
如果样本数为零则返回 true,否则返回 false |
void reset(Info *info) |
丢弃所有样本 |
add(DistBase &) |
从另一个具有 DistBase 的 Stats 类(例如 Stats::Distribution)合并样本 |
Stats::VectorDistribution
存储一个分布的向量,其中向量的每个元素都具有与 Stats::Distribution 相似的函数签名。
| 函数签名 | 描述 |
|---|---|
VectorDistribution & init(size_type size, Counter min, Counter max, Counter bkt) |
初始化一个包含 size 个分布的向量,其中 min 是每个分布直方图跟踪的最小值,max 是每个分布直方图跟踪的最大值,bkt 是每个分布中每个桶的值数量 |
Derived & subname(off_type index, const std::string &name) |
为给定索引处的统计信息添加名称 |
Derived & subdesc(off_type index, const std::string &desc) |
为给定索引处的统计信息添加描述 |
size_type size() const |
返回向量中的元素数量 |
bool zero() const |
如果每个分布的样本数都为 0 则返回 true,否则返回 false |
operator[](off_type index) |
获取给定索引处分布的引用,例如 dists[1].sample(2, 3) |
Stats::VectorStandardDeviation
存储一个标准差的向量,其中向量的每个元素都具有与 Stats::StandardDeviation 相似的函数签名。
| 函数签名 | 描述 |
|---|---|
VectorStandardDeviation & init(size_type size) |
初始化一个包含 size 个标准差的向量 |
Derived & subname(off_type index, const std::string &name) |
为给定索引处的统计信息添加名称 |
Derived & subdesc(off_type index, const std::string &desc) |
为给定索引处的统计信息添加描述 |
size_type size() const |
返回向量中的元素数量 |
bool zero() const |
如果每个分布的样本数都为 0 则返回 true,否则返回 false |
operator[](off_type index) |
获取给定索引处标准差的引用,例如 dists[1].sample(2, 3) |
Stats::VectorAverageDeviation
存储一个平均偏差的向量,其中向量的每个元素都具有与 Stats::AverageDeviation 相似的函数签名。
| 函数签名 | 描述 |
|---|---|
VectorAverageDeviation & init(size_type size) |
初始化一个包含 size 个平均偏差的向量 |
Derived & subname(off_type index, const std::string &name) |
为给定索引处的统计信息添加名称 |
Derived & subdesc(off_type index, const std::string &desc) |
为给定索引处的统计信息添加描述 |
size_type size() const |
返回向量中的元素数量 |
bool zero() const |
如果每个分布的样本数都为 0 则返回 true,否则返回 false |
operator[](off_type index) |
获取给定索引处平均偏差的引用,例如 dists[1].sample(2, 3) |
Stats::Formula
存储作为 Stats 对象的一系列算术运算结果的统计量。注意,在下面的函数中,Temp 可以是任何持有统计信息的 Stats 类(包括向量统计)、公式或数字(例如 int, double, 1.2)。
| 函数签名 | 描述 |
|---|---|
const Formula &operator=(const Temp &r) |
将未初始化的 Stats::Formula 赋给给定的根 |
const Formula &operator=(const T &v) |
将公式赋给一个统计量、另一个公式或一个数字 |
const Formula &operator+=(Temp r) |
向当前公式加上一个统计量、另一个公式或一个数字 |
const Formula &operator/=(Temp r) |
将当前公式除以一个统计量、另一个公式或一个数字 |
void result(VResult &vec) const |
将公式的求值结果赋给给定的向量;如果公式没有向量分量(公式中没有一个变量是向量),则向量大小为 1 |
Result total() const |
以双精度浮点数形式返回 Stats::Formula 的求值结果;如果公式确实有向量分量(公式中有一个变量是向量),则通过将其设置为向量中所有元素的总和将其转换为标量 |
size_type size() const |
如果根元素不是向量则返回 1,否则返回向量的大小 |
bool zero() |
如果 result() 中的所有元素都为 0 则返回 true,否则返回 false |
使用 Stats::Formula 的示例:
cpp
Stats::Scalar totalReadLatency;
Stats::Scalar numReads;
Stats::Formula averageReadLatency;
averageReadLatency = totalReadLatency / numReads; // 注意:赋值通常在构造函数外进行,但初始化可以在构造函数内使用 ADD_STAT
附录:迁移至新的统计跟踪风格
一种新的统计跟踪风格
gem5 统计信息具有扁平结构,不了解包含统计对象的 SimObject 的层次结构。这导致了不同统计信息具有相同名称的问题,更重要的是,操作 gem5 统计信息的结构并非易事。此外,gem5 没有提供将统计对象集合分组到不同组中的方法,而这对于维护大量统计对象非常重要。
最近的一次提交引入了 Stats::Group,这是一个旨在保存属于一个对象的所有统计信息的结构。新结构提供了一种显式的方法来反映 SimObject 的层次结构。Stats::Group 还使得维护应分组到不同集合中的大量 Stats 对象变得更加明确和容易,因为可以在一个 SimObject 中创建几个 Stats::Group 并将它们合并到该 SimObject(它也是一个知晓其子 Stats::Group 的 Stats::Group)。
总的来说,这是迈向更具结构化的 Stats 格式的一步,这将有助于操作 gem5 中统计信息的整体结构,例如过滤统计信息以及将 Stats 生成为更标准化的格式,如 JSON 和 XML,而这些格式在各种编程语言中有大量的支持库。
迁移至新的统计跟踪风格
注意:强烈鼓励迁移到新风格;但是,旧风格的统计(即具有扁平结构的统计)仍然受支持。
本指南提供了如何迁移到 gem5 统计跟踪新风格的广泛视角,并指出了一些展示如何完成迁移的具体示例。
ADD_STAT
ADD_STAT 是一个宏,定义如下:
#define ADD_STAT(n, ...) n(this, # n, __VA_ARGS__)
此宏旨在 Stats::Group 构造函数中用于初始化 Stats 对象。换句话说,ADD_STAT 是调用 Stats 对象构造函数的别名。例如,ADD_STAT(stat_name, stat_desc) 等同于:
cpp
stat_name.parent = 定义 `stat_name` 的 `Stats::Group`
stat_name.name = "stat_name"
stat_name.desc = "stat_desc"
这适用于大多数 Stats 数据类型,但 Stats::Formula 除外,ADD_STAT 宏可以处理一个指定公式的可选参数。例如,ADD_STAT(ips, "Instructions per Second", n_instructions / sim_seconds)。
一个使用 ADD_STAT 的示例用例(在本节中我们称此示例为"示例 1")。此示例也作为构建 Stats::Group 结构的模板。
cpp
protected:
// 定义一个统计组
struct StatGroup : public Stats::Group
{
StatGroup(Stats::Group *parent); // 构造函数
Stats::Histogram histogram;
Stats::Scalar scalar;
Stats::Formula formula;
} stats;
// 定义已声明的构造函数
StatGroup::StatGroup(Stats::Group *parent)
: Stats::Group(parent), // 初始化基类
ADD_STAT(histogram, "A useful histogram"),
ADD_STAT(scalar, "A number"), // 这与 ADD_STAT(scalar, "A number") 相同
ADD_STAT(formula, "A formula", scalar / some_other_scalar) // 假设 some_other_scalar 是另一个已定义的 Stats::Scalar
{
// 在构造函数体内进行额外的初始化(例如,设置直方图桶数、标志等)
histogram.init(num_bins); // 假设 num_bins 已定义
scalar
.precision(2) // 设置精度
.flags(condition ? Stats::none : Stats::nozero); // 根据条件设置标志
}
迁移到新风格
这些是将统计信息转换到新风格的具体示例:这里, 这里 和 这里。
将统计信息迁移到新风格涉及:
-
创建一个
struct Stats::Group,并将所有统计变量移至其中。此结构体的范围应为protected。统计变量的声明通常在头文件中。 -
去掉
regStats(),并将统计变量的初始化移至Stats::Group构造函数,如示例 1 所示。 -
在头文件和 cpp 文件中,所有统计变量现在都位于
Stats::Group结构体下,因此应在前面加上新创建的Stats::Group的名称(例如stats.)。 -
更新类构造函数以初始化
Stats::Group变量。通常,如果变量名是stats,则在构造函数中添加stats(this)。
一些例子: