上一篇: GEM5 Garnet Standalone 命令行与stats.txt结果分析
时隔几年,竟然还是自己看自己的博客才看懂怎么操作。
补一点具体的实验和步骤,以及命令行 :以及在具体的代码之前,聊一下我对gem5的代码分层: 用户使用层,编译配置层(build+config),自我创造层(自己写source code,比如自己写一个控制单元)。
0. 基础的设置
./build/NULL/gem5.debug -d m5out/garnetStandalone configs/example/garnet_synth_traffic.py \
--num-cpus=16 \
--num-dirs=16 \
--network=garnet \
--topology=Mesh_XY \
--mesh-rows=4 \
--sim-cycles=500000000 \
--synthetic=uniform_random \
--injectionrate=0.01 --single-sender-id=-1
结果是
system.ruby.network.average_flit_latency 5806.473367 (Unspecified)
system.ruby.network.average_flit_network_latency 4806.473367 (Unspecified)
system.ruby.network.average_flit_queueing_latency 1000 (Unspecified)
./build/NULL/gem5.debug -d m5out/garnetStandalone configs/example/garnet_synth_traffic.py \
--num-cpus=16 \
--num-dirs=16 \
--network=garnet \
--topology=Mesh_XY \
--mesh-rows=4 \
--sim-cycles=1000000000 \
--synthetic=uniform_random \
--injectionrate=0.1 --single-sender-id=-1
( 这一段的运行时间hostSeconds=267.38 秒)
结果:system.ruby.network.average_flit_latency 6266.077169 (Unspecified)
system.ruby.network.average_flit_network_latency 5031.247101 (Unspecified)
system.ruby.network.average_flit_queueing_latency 1234.830067 (Unspecified)
system.ruby.network.average_flit_vnet_latency | 4042.027982 | 4044.814804 | 5426.491156 (Unspecified)
这里注意到,后面的延迟要高一些的,原因很简单,网络是从空的时候开始的。换言之,warmup 很重要,或者额外的不注入包的拖尾时间也很重要。
0.1 baseline 的设置
打开config.ini 搜 buffers_per_ctrl_vc=1 buffers_per_data_vc=4 vcs_per_vnet=4,。
做noc的,慢慢翻都能找到这些参数。这里放一下具体准却的英文方便直接搜索,不用慢慢翻看的眼睛都瞎了。
0.2 尝试让网络堵。单flit的默认vn为例子。
我的一个研究目标是探讨一下noc网络会堵的时候调控,所以得先作死让网络堵起来。
在 用户使用层,编译配置层(build+config),自我创造层(自己写source code,比如自己写一个控制单元)中的用户使用层就自带了这个功能,不用自己费力气写:
–vcs-per-vnet= 1
那我们使用一下:
./build/NULL/gem5.debug -d m5out/garnetStandalone configs/example/garnet_synth_traffic.py \
--num-cpus=16 \
--num-dirs=16 \
--network=garnet \
--topology=Mesh_XY \
--mesh-rows=4 \
--sim-cycles=1000000000 \
--synthetic=uniform_random \
--injectionrate=0.1 --single-sender-id=-1 --vcs-per-vnet=1
结果6942,比baseline 6266恶化了 大概10%
system.ruby.network.average_flit_latency 6942.808866 (Unspecified)
system.ruby.network.average_flit_network_latency 5333.565192 (Unspecified)
system.ruby.network.average_flit_queueing_latency 1609.243675 (Unspecified)
system.ruby.network.average_flit_vnet_latency | 4135.204766 | 4136.569916 | 5812.774157 (Unspecified)
system.ruby.network.average_flit_vqueue_latency | 1114.711294 | 1157.521842 | 1798.551392 (Unspecified)
packet:
system.ruby.network.average_hops 2.501919 (Unspecified)
system.ruby.network.average_packet_latency 6488.683972 (Unspecified)
system.ruby.network.average_packet_network_latency 5131.802033 (Unspecified)
system.ruby.network.average_packet_queueing_latency 1356.881939 (Unspecified)
system.ruby.network.average_packet_vnet_latency | 4135.204766 | 4136.569916 | 7124.207510 (Unspecified)
system.ruby.network.average_packet_vqueue_latency | 1114.711294 | 1157.521842 | 1798.552591
1. 直接大拥堵设置: vcs_per_vnet=1.
1.1 使用 multiple flit
在使用层,bash 命令里 –inj-vnet= 2 即可。控制变量,我们也把 --injectionrate=0.1 变为0.02
1.1.1 5flit 和baseline 的vc per vn=4
./build/NULL/gem5.debug -d m5out/garnetStandalone configs/example/garnet_synth_traffic.py \
--num-cpus=16 \
--num-dirs=16 \
--network=garnet \
--topology=Mesh_XY \
--mesh-rows=4 \
--sim-cycles=1000000000 \
--synthetic=uniform_random \
--injectionrate=0.02 --single-sender-id=-1 --inj-vnet=2
1.1.2 5flit 和主动作死 的vc per vn=1
./build/NULL/gem5.debug -d m5out/garnetStandalone configs/example/garnet_synth_traffic.py \
--num-cpus=16 \
--num-dirs=16 \
--network=garnet \
--topology=Mesh_XY \
--mesh-rows=4 \
--sim-cycles=1000000000 \
--synthetic=uniform_random \
--injectionrate=0.02 --single-sender-id=-1 --vcs-per-vnet=1 --inj-vnet=2
对比不调节vn的结果,packet级别,7675恶化到8043,flitdelay 从6224恶化到6683,10%左右。。 而且可以看出,主要是堵在queueing这边,不主动作死之前,queue是1000等于没压力。 即使作死后,noc网络的运输也依旧没压力,因为网络的delay是6675和6793,有恶化但差距不大。
遵循文章的设置,每20k CPU cycles是一个epoch。一个epoch也就是 是20000×500=10000000,10e7也就是 1kw ticks 。 我们总运行时间是10e9,所以我们跑了100个epoch。
我们注入的包数是多少呢: 319870 。除以100再除以16,我们的平均注入包是一个epoch,每个节点200个packet。
而参考文献2里图里,大部分的包是30左右的packet注入率。
好好好,可能是因为参考文献2是full system吧,这么低的注入率竟然调控还有效,就离谱。 我们先沿用参考文献1的4x4小noc看看。 参考文献1的纯noc中,uniformrandom 与静态调节相比,均匀随机流量的全局平均数据包延迟改善了 68 个周期(百分比为 48.3%) ,也就是在静态其实起了负面效果,是141左右。 baseline,10 /0.126是79.3。
而 我们得到的,是76-80左右的cpu cycle,是150-160左右的routercycle。 是不是参考文献1在2014年用的gems,cycles数是cpu和router一致啊,ticks是后面的更新了。(跑去看了一眼gems :https://research.cs.wisc.edu/gems/doc/gems-wiki/moin.cgi/Garnet ,发现当年是5-stage的pipeline也没说是不是one cycle内的。现代gem5是one cycle内的)
1.1.3 5flit 和主动无限资源 的vc per vn=100
先给个100 vc channel看看。
./build/NULL/gem5.debug -d m5out/garnetStandalone configs/example/garnet_synth_traffic.py \
--num-cpus=16 \
--num-dirs=16 \
--network=garnet \
--topology=Mesh_XY \
--mesh-rows=4 \
--sim-cycles=1000000000 \
--synthetic=uniform_random \
--injectionrate=0.02 --single-sender-id=-1 --inj-vnet=2 --vcs-per-vnet=100
跑跑结果看吧:首先运行时间来到了750s,十多分钟了。
ystem.ruby.network.average_flit_latency 6224.702767 (Unspecified)
system.ruby.network.average_flit_network_latency 5224.702767 (Unspecified)
system.ruby.network.average_flit_queueing_latency 1000 (Unspecified)
system.ruby.network.average_flit_vnet_latency | nan | nan | 5224.702767 (Unspecified)
system.ruby.network.average_flit_vqueue_latency | nan | nan | 1000 (Unspecified)
system.ruby.network.average_hops 2.499983 (Unspecified)
system.ruby.network.average_packet_latency 7675.216574 (Unspecified)
system.ruby.network.average_packet_network_latency 6675.216574 (Unspecified)
system.ruby.network.average_packet_queueing_latency 1000 (Unspecified)
结果和vc=4一模一样,还确认了一下确实是100:
早知道这样我都不跑全系统了,单noc的模拟都没啥改变,跑全系统纯属浪费时间啊啊啊啊啊。
不过好处是知道了(一段时间以后)方向了,先把noc的这个注入率之类的整好,再使用fs接近的noc注入情况对noc调整。
1月30的深夜12点多了,赶最后一般地铁去了,明天周五再来!
1月31回来了,现在的方向是:尝试复现静态的。
先看参考文献作者1的硕士论文(硕士论文的成果后续发的参考1)第16页:以及我觉得,注入率0的时候应该是搞错了。 0的时候应该是只发一个包,但是这个queueingdelay和网络delay应该是搞反了。
然后看看设置:5个flit和1个flit的包的比例是1:8。 这个比例不知道咋来的,最多也就是某个参考文献里提了一嘴或者一个经验值。
总时长是10e7cycles,对应我们就是10e7×(500) ticks 是10e7 router cycles,或者10e7×1000是10e7的cpucycles。 当然,够长就差不多,因为趋势已经很明显了。
趋势是什么呢:文章也说了,
对于这个4x4的noc情况来说,注入率太大了就直接干爆了noc。后面只会越堵越多。顺带一提,Dally的书有公式来计算最大的throughput,图里这个公式更像是从经验值倒推的一个式子。
这也反映了noc调控的一个痛点:网络在一段时间内的平均流量需要刚好就在某个临界值附近,调控流量才有意义。 太小的流量不用调,太大的流量调了没用。 然后流量在每个细微的时刻波动一下,我们的策略拉回来,才有意义。
在看一张图,大概意思就是注入率如果高了,也不能提高链路利用率。 注入率对于文中的这个场景,就在0.2左右比较好。
然后在看一下该作者对admission control的一部分想法(还得是硕士论文说人话,读发表的文章经常不知道细节是啥)。作者的意思就是,假设我已经知道了0.02就是最吼滴(这个前提条件,我认为是一个大弱点,所以后续需要闭环/full system来补充),但是很难明确的确定一个具体的值来知道这个时候网络堵了(这里我觉得不太成立,搞点提前量呗,或者再搞点延后量都行,说白了都是经验值,网络traffic pattern要是变一下,这个leaky bucket的设置也得变,完全没必要搞这么精确。)
以及,可能峰值注入率到了,但是网络是有冗余的呀,需要考虑网络内的链路使用情况。就像堵车一样,情况1:路口的车一下子来了几百台车,但是路很空,那没必要一分钟只让一台车进;情况2:路已经堵了,路口就是只有一辆车,那也得封高速。
我跑一个简单的结果,然后放一点图吧, 为了赶时间,把cycles放小了
./build/NULL/gem5.debug -d m5out/garnetStandalone configs/example/garnet_synth_traffic.py
–num-cpus=16
–num-dirs=16
–network=garnet
–topology=Mesh_XY
–mesh-rows=4
–sim-cycles=10000000
–synthetic=uniform_random
–single-sender-id=-1 --inj-vnet=2 --vcs-per-vnet=100 --injectionrate=0.01/0.02
简单看一下,调控的目标 应该在0.1-0.15之间。下一步就是i加入调控手段咯。到点了,今天赶12点的地铁!
针对 非均匀负载
参考文献1提到,非均匀负载要表现好一点。 好好好,那我们也试试permutation这个traffic----不是,gem5怎么没这个了,只有uniform_random’, ‘tornado’, ‘bit_complement’, ‘bit_reverse’, ‘bit_rotation’, ‘neighbor’, ‘shuffle’, and ‘transpose’ 这几种了。
gemini说用shuffle,那我们用shuffle吧。后续可以看源代码,看看这个shuffle到底是啥shuffle。
算了还是没忍住,现在i就看了源代码:
只看shuffle,就是一半对另一半节点,每个节点只给固定的一个目的地节点发,从一自终,还挺深情。
0205更新:
我们看下图,首先就是baseline1的queueing要小。
然后静态的才能减少网络delay,代价是queueingdelay增加。
再然后,fuzzycontrol可以降低这个代价,达成整体的提高。
下图的意思就是网络拥堵的时候调节流量才有用,不然没用(路很空,没必要把车堵在路口不让进去)。