gem5 添加自定义打印信息到stats.txt & debug print信息

简介

更改gem5源代码后,有时候想看看改变有没有成功,效果怎么样,需要监控一下结果.有两种方式,debug模式下,命令行窗口打印出来,就像cpp的 cout或python的print一样,这是dprintf. 或者利用gem5自带的输出功能,本来它会有一个统计文件叫stat.txt,作为输出,我们可以复用add_stat功能,将我们需要打印的值,打印到stat.txt里

1 . dprintf

DPRINTF is a debugging trace facility that allows one to

  • selectively enable tracing statements. To use DPRINTF, there must
  • be a function or functor called name() that returns a const
  • std::string & in the current scope.

2.1 GEM5传统的扁平化统计方式

非常直观,如果要添加一个统计量,直接定义一个新变量

Stats::Scalar totalReadLatency;

然后再需要给它赋值的时候写代码给它赋值就好了,比如每得到一个包的onePacketreadlatency,

totalReadLatency =totalReadLatency + onePacketreadlatency 

2.2 新的结构化统计: 使用宏 ADD_STAT 添加到stats.txt

gem5之前统计太扁平了,所以新的方法支持更结构化的统计, 旨在在构造函数中使用Stats::Group来初始化Stats对象。
老的方法也支持. 个人评价是更复杂更华丽胡哨,初学者可以不用2.2的方法,只用2.1传统的统计方式就完全够用了.

定义

在 gem5/src/base/stats/group.hh 中
#define ADD_STAT(n, …) n(this, #n, VA_ARGS)

ADD_STAT 宏通常在 gem5 源代码的统计系统相关的头文件中定义。这些头文件位于 src/base/stats/ 目录中。

使用例子

2.1 传统统计方式的例子

我们以NI为例子, src/mem/ruby/network/garnet/NetworkInterface.cc这个CPP代码中,会调用一个increment_flit_network_latency函数:

NetworkInterface::incrementStats(flit *t_flit)
{
	    m_net_ptr->increment_flit_network_latency(network_delay, vnet);
  		m_net_ptr->increment_flit_queueing_latency(queueing_delay, vnet);
}

increment_flit_queueing_latency函数定义在 src/mem/ruby/network/garnet/GarnetNetwork.hh内,具体细节如下:

   void
    increment_flit_queueing_latency(Tick latency, int vnet)
    {
        m_flit_queueing_latency[vnet] += latency;
    }

而 m_flit_queueing_latency就是一个很简单很清晰的统计变量: 定义在 src/mem/ruby/network/garnet/GarnetNetwork.hh内

 statistics::Vector m_flit_queueing_latency;

它是一个vector,长度其实是3,因为garnet 只有3个vnet. 里面有三个scalar值,每个scalar值对应一个vn网络的这个变量(queueing_latency)的统计. 它的功能就是统计三个vn网络内,各自的网络delay和queueing_delay之和.

统计了怎么打印输出

刚刚的部分,cpp程序会计算 m_flit_queueing_latency的值,但是这个值很显然只在内存里,并不会通过io操作打印成stats.txt里的值.
打印的部分是在 src/mem/ruby/network/garnet/GarnetNetwork.cc的函数void
GarnetNetwork::regStats()里实现的

void
GarnetNetwork::regStats()
{
   m_flit_queueing_latency
        .init(m_virtual_networks)
        .name(name() + ".flit_queueing_latency")
        .flags(statistics::oneline)
        ;
        }

这里的name()是自己的 “name()”,作为garnetwork.cc里的name(),他的值是system.ruby.network.
有点需要init有点不需要: 是否调用 init() 取决于统计变量的类型和所需的初始化方式。数组或列表类型的统计变量需要使用 init() 来设定其大小,而单一值类型的统计变量则不需要这样的初始化过程。

验证: m_flit_queueing_latency flit_queueing_latency

我们可以看到,stats.txt里是有下面两个量的截图的.
在这里插入图片描述
在这里插入图片描述
如果换用不启用ruby的network的结果,则搜不到这些flit的统计量.
这里的值为0,是因为m_demand_accesses也是0,也就是说这个统计里,并没有用网络传包.

2.2的例子

例如已经用的例子。
在这里插入图片描述

使用时我们先定义一个结构体

** Statistics */
    struct TableWalkerStats : public statistics::Group
    {
        TableWalkerStats(statistics::Group *parent);
        statistics::Scalar walks;
 
    } stats;

然后调用

TableWalker::TableWalkerStats::TableWalkerStats(statistics::Group *parent)
    : statistics::Group(parent),
    ADD_STAT(walks, statistics::units::Count::get(),
             "Table walker walks requested"),
  
{
  
}

另一个例子 GpuTLBStats是创建的结构体

GpuTLB::GpuTLBStats::GpuTLBStats(statistics::Group *parent)
        : statistics::Group(parent),
   ADD_STAT(localNumTLBAccesses, "Number of TLB accesses"),
    {
    
    }

其中 statistics来自与include的 statistics.hh

#include “base/statistics.hh”

我的实例

https://blog.csdn.net/weixin_37702021/article/details/124872704提到的,gatech课程里的extract_network_stats.sh

echo > network_stats.txt
grep "packets_injected::total" m5out/stats.txt | sed 's/system.ruby.network.packets_injected::total\s*/packets_injected = /' >> network_stats.txt
grep "packets_received::total" m5out/stats.txt | sed 's/system.ruby.network.packets_received::total\s*/packets_received = /' >> network_stats.txt
grep "average_packet_queueing_latency" m5out/stats.txt | sed 's/system.ruby.network.average_packet_queueing_latency\s*/average_packet_queueing_latency = /' >> network_stats.txt
grep "average_packet_network_latency" m5out/stats.txt | sed 's/system.ruby.network.average_packet_network_latency\s*/average_packet_network_latency = /' >> network_stats.txt
grep "average_packet_latency" m5out/stats.txt | sed 's/system.ruby.network.average_packet_latency\s*/average_packet_latency = /' >> network_stats.txt
grep "flits_injected::total" m5out/stats.txt | sed 's/system.ruby.network.flits_injected::total\s*/flits_injected = /' >> network_stats.txt
grep "flits_received::total" m5out/stats.txt | sed 's/system.ruby.network.flits_received::total\s*/flits_received = /' >> network_stats.txt
grep "average_flit_queueing_latency" m5out/stats.txt | sed 's/system.ruby.network.average_flit_queueing_latency\s*/average_flit_queueing_latency = /' >> network_stats.txt
grep "average_flit_network_latency" m5out/stats.txt | sed 's/system.ruby.network.average_flit_network_latency\s*/average_flit_network_latency = /' >> network_stats.txt
grep "average_flit_latency" m5out/stats.txt | sed 's/system.ruby.network.average_flit_latency\s*/average_flit_latency = /' >> network_stats.txt
grep "average_hops" m5out/stats.txt | sed 's/system.ruby.network.average_hops\s*/average_hops = /' >> network_stats.txt

但是这里很多的变量名在23.0版本已经变了.

我们运行10000cycle,命令行如下
./build/NULL/gem5.debug configs/example/garnet_synth_traffic.py
–num-cpus=16
–num-dirs=16
–network=garnet
–topology=Mesh_XY
–mesh-rows=4
–sim-cycles=10000 --inj-vnet=0
–synthetic=uniform_random
–injectionrate=1

stats.txt结果如下.可以看到发出了318flit 只有76个flit收到了
在这里插入图片描述

如果我们发出100万cycles
./build/NULL/gem5.debug configs/example/garnet_synth_traffic.py
–num-cpus=16
–num-dirs=16
–network=garnet
–topology=Mesh_XY
–mesh-rows=4
–sim-cycles=1000000 --inj-vnet=0
–synthetic=uniform_random
–injectionrate=1
inject注入了15972,收到了15897,说明还有100不到的flit没有收到.
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值