在使用王小航老师课题组开源的Gem5代码进行大规模的Chiplet并行仿真时,有个关键问题是:为什么原来的gem5不可以进行大规模仿真?为什么精度不够?也是论文提出的背景:
(20条消息) 傻白探索Chiplet,A Methodology for Simulating Multi-chiplet Systems UsingOpen-source Simulators(十)_好啊啊啊啊的博客-CSDN博客
当时感受不是很清楚,以我现在的观点来看,无法进行大规模的并行仿真是由于Gem5虽然支持多核仿真,但是Gem5本身是在单核上运行的,无论你主机有多少个核只用得上一个,极大地限制了Gem5的运行,我测过,就跑一个很简单的256*256的矩阵乘法,用默认配置(开启L1Cache + 512MB 内存 + AtomicSimpleCPU)在64核上得半小时,如果你改用TimingSimpleCPU你还不一定能跑起来,因此大规模并行仿真确实不太行;
精度不够,考虑两个原因,精度要高可以考虑使用O3 CPU模型,但核多了会很卡,另一方面你在测算某个benchmark时,计算完成虽有stats.txt可以看统计结果,但是如果运行完成后你不及时结束,sim_tick和final_tick以及一些和时间相关的参数也会跟着变大;此外,在考虑Chiplet通信时,因为论文中使用的是文件读写来实现通信,但是实际中并不是这样,你可能要考虑实际传输的链路时延和能耗、路由器转发也需要时间和能耗、interposer是否存在等等,这些在gem5模拟器中是没有被考虑到的,因为gem5是一个通用CPU模拟器,这是我觉得论文说Gem5精度不够的原因。
综上,论文提出了用gem5来模拟系统结构并得到通信记录,再通过popnet模拟器来测算这个通信记录的延时和能耗,这个就给了你比较多的发挥空间,你可以选用不同的拓扑结构、不同的路由策略、是否考虑中介层等等。但是popnet模拟器的文档对我这样的小白来说还是不够清晰,它本身提供了多种路由策略,但是比较模棱两可的是:
抱着以上疑问,我开启了阅读popnet源码的不归之路,我只想顺顺利利的做个靠谱的实验 (T_T)
获取popnet模拟器代码:
git clone https://gitee.com/hic_0757/popnet_modified.git
目录
一、相关知识:
二、Q&A
1. 如何选取路由策略?选取依据是什么?不同的路由策略有何差异
2. 选择的路由策略中,拓扑何如?需要怎样的输入才能让这个路由算法跑起来?
3. 如果跑出结果了,我如何判断这个输出是对的,是和我的输入文件能够对应起来的?
三、源码记录
由于我是小白,之前并未接触过片上网络模拟器,查看论文之后才知道popnet模拟器中提到的微片flit是何意,常用的交换技术有:电路交换,存储转发,虚切入,虫孔等等,以下:
报文交换将消息划分成固定长度的报文,每个报文的前几个字节包含路由和控制信息。如果消息较短且发送频繁,那么,报文交换是有优势的。
在poopnet模拟器中,A Methodology for Simulating Multi-chiplet Systems UsingOpen-source Simulators论文中使用的应该是虫孔机制。从性能的角度,VCT 优于 WH;从代价的角度,WH 优于 VCT。
选取依据:看你想要啥样的拓扑结构,前两个是我觉得路由节点是mesh的(哦买噶,怎么和论文说的Torus是悖论,之后再看看确定一下);你想要自定义托拓扑的话就第五个,可以自己写一个mesh、crossbar或者star的网络。
拓扑勉强也算在上个问题说了,有个问题就是,作者应该是为了图方便,在源节点向目的节点发送数据时,固定写“0 x 0 y”,因此关于ary_number_就是指每个维度上的路由器个数,比如一个二维的9*9网络的此参数就是9。即使我们只有9个节点,为了不超过这个拓扑的9*9大小,我们仍然需要指定ary_number_=9。
输入:如果是1和2的话,无需拓扑结构,它内部自己应该有实现;如果是第5个需要自定义的拓扑结构(源码中有教如何构建)和通信的trace文件;第6个除了需要拓扑结构、通信的trace还有一份额外的配置文件。
这个popnet模拟器数据注入是根据trace文件的时钟周期来的,到那个时钟周期就会有数据注入(触发EVG_事件),继而调用ROUTER_事件,在相应触发CREDI_和WIRE_。如此,如果你的时钟越大,你路由的时间就越长,最终查看你总共完成的packet数目是否等于trace文件中的消息记录,相等就代表已完成。
注意:整个路由过程本来就是一个死循环,时刻在检测是否有新数据进入。
以下是我阅读源码时的一些记录,仅供参考,有错误还请各位大佬批评指正,我只是个弱小的菜菜--\(˙<>˙)/--:
main.py:
int main(int argc, char *argv[])
{
try {
SRGen random_gen;
configuration c_par(argc, argv); //使用命令行参数 argc 和 argv 创建一个 configuration 类的实例 c_par,用于读取程序的配置参数。
cout<
mess_queue.h和mess_queue.cc:主要是创建优先级队列(重载<运算符,以时钟周期作为优先级,始终越小越靠前),以及消息的入队、出队操作,通过构造函数进行初始化。以及simulator()函数负责整个过程的模拟调用,setInitEvent()函数根据不同的路由算法,将其包装成不同的路由事件,放到消息队列中。
mess_queue(time_type start_time=TIME_0); //TIME_0=0或无限接近于0
void mess_queue::simulator() {
//changed at 2020-5-23
//static uint64_t wireMsgCnt=0,creditMsgCnt=0;
//time_type report_t = 0;
time_type report_t=TIME_0; // 0
long total_incoming = 0;
//根据不同的路由算法,将其包装成不同的路由事件,放到消息队列中
setInitEvent();
//修改此循环
//when mess queue is not empty and simulation deadline has not reach
// 事件队列不为空,时间还没有达到指定的最大周期
while(m_q_.size() > 0 && (current_time_ <= (configuration
::ap().sim_length()))) {
//changed at 2021-10-26
//mess_event current_message = * get_message();
// 返回消息队列中优先级最高的事件(按照时间排序,路由事件都用0作为其优先级,意味着路由事件是最先得到处理的)
mess_event current_message=get_message();
//changed at 2020-5-23
//输出日志
//logfile<(current_time_ <= ((current_message.
event_start()) + S_ELPS_)));
//if(current_time_>current_message.event_start()+S_ELPS_)continue;
// 返回事件的开始时间
current_time_ = current_message.event_start();
if(current_time_ > report_t) {
cout<<"Current time: "<
sim_foundation.h和sim_foundation.cc:
构造函数: