ずいぶん大昔の記事を引っ張り出してきたが、RASの解析などを行うにあたり、BOOMの実装を調べたくて、BOOMの実性能がどうなっているのか調べたくなってきたので調査している。
gem5を使えばBOOMのパイプライントレースの解析を行うことができる。これで自前でコンパイルしたCoremarkを解析して、BOOMの性能を解析したい。
-O3 -funroll-loops を加えたCoremarkのコンパイル
funroll-loopsと-O3を加えて、評価用のCoremarkプログラムをコンパイルした。RocketもBOOMも64bitで動作するし、自作ISSも64bitモードに対応しているのでこれで比較する。
start_time(), stop_time()の間の命令数
grep -e 80006a90 -e 80006aa0 coremark.sw.log 15260:M:MBar:[0000000080006a90][P000080006a90] 00000033 : add r00,r00,r00 r00=>0000000000000000 r00=>0000000000000000 370114:M:MBar:[0000000080006aa0][P000080006aa0] 00000033 : add r00,r00,r00 r00=>0000000000000000 r00=>0000000000000000
というわけで命令数的には35万命令程度なのだが、-funroll-loops
を加えると命令数が増えてしまった。不思議。
BOOM(2-way)での実行
BOOMで当該バイナリを実行して、同様にstart_time()
、stop_time()
のサイクル数を解析した。
make CONFIG=BOOMConfig output/coremark.riscv.out ../boom/util/pipeview-helper.py -f output/coremark.riscv.out > cleaned_trace.out /work/gem5/util/o3-pipeview.py -o pipeview.out --colorcleaned_trace.out
前の記事にも書いたが、output/coremark.riscv.outの先頭にある1行を削除しないと解析されないので注意。
$ grep -e start_time -e stop_time coremark.dmp 0000000080006a90 <start_time>: 80006a98: 1e02aa23 sw zero,500(t0) # 8000dc88 <start_time_val> 0000000080006aa0 <stop_time>: 80006aa8: 1e02a023 sw zero,480(t0) # 8000dc84 <stop_time_val> $ grep -e 80006a90 -e 80006aa0 pipeview.out [..................f..di...cr....................................................]-( 1168480000) 0x0080006a90.0 add zero, zero, zero [ 619748] [====================f==di=======================================================]-( 1168480000) 0x0080006aa0.0 -----add zero, zero, zero [ 619752] [=========================================================f======================]-( 1662480000) 0x0080006a90.0 -----add zero, zero, zero [ 1284475] [.....................................................................f..di...cr.]-( 1666800000) 0x0080006aa0.0 add zero, zero, zero [ 1291132] [======================f==di=====================================================]-( 1671200000) 0x0080006a90.0 -----add zero, zero, zero [ 1296453] [========================f=======================================================]-( 1671200000) 0x0080006aa0.0 -----add zero, zero, zero [ 1296457]
ちなみにpipeiew.out
の見方だが、------
がアセンブリ命令の前についているのは、パイプラインフラッシュされる対象の命令なので無視。こう見ると、start_time()
からstop_time()
までのサイクル数は大よそ
あれ、サイクル数的にはだいぶ増えたぞ?
途中のサイクルを見ていると、
[................................................................f..di..c.r......]-( 1279680000) 0x0080003690.0 lh a2, 0(s8) [ 764124] [................................................................f..di...cr......]-( 1279680000) 0x0080003694.0 addw a4, s10, s6 [ 764125] [.................................................................f..di...cr.....]-( 1279680000) 0x0080003698.0 addiw a5, a5, 4 [ 764126] [.................................................................f..d.i...cr....]-( 1279680000) 0x008000369c.0 mulw s10, ra, s7 [ 764127] [==================================================================f==d==========]-( 1279680000) 0x00800036a0.0 -----addw t6, t6, a3 [ 764128] [==================================================================f==d==========]-( 1279680000) 0x00800036a4.0 -----mulw ra, t5, t0 [ 764129] [===================================================================f==d=========]-( 1279680000) 0x00800036a8.0 -----addw s7, t6, s10 [ 764130] [===================================================================f==d=========]-( 1279680000) 0x00800036ac.0 -----mulw a6, t2, a2 [ 764131] [====================================================================f==d========]-( 1279680000) 0x00800036b0.0 -----addw t4, s7, ra [ 764132] [====================================================================f==d========]-( 1279680000) 0x00800036b4.0 -----addw t6, t4, a6 [ 764133] [=====================================================================f==d=======]-( 1279680000) 0x00800036b8.0 -----bne t3, a5, pc - 224 [ 764134] [======================================================================f==d======]-( 1279680000) 0x00800035d8.0 -----addw s8, a4, s6 [ 764135] [======================================================================f==d======]-( 1279680000) 0x00800035dc.0 -----slli s7, a5, 32 [ 764136] [=======================================================================f==d=====]-( 1279680000) 0x00800035e0.0 -----slli t2, a4, 32 [ 764137] [=======================================================================f==d=====]-( 1279680000) 0x00800035e4.0 -----addiw t5, a5, 1 [ 764138] [========================================================================f==d====]-( 1279680000) 0x00800035e8.0 -----srli a3, s7, 32 [ 764139] [========================================================================f==d====]-( 1279680000) 0x00800035ec.0 -----srli s10, t2, 32 [ 764140] [=========================================================================f==d===]-( 1279680000) 0x00800035f0.0 -----addw a2, s8, s6 [ 764141] [=========================================================================f==d===]-( 1279680000) 0x00800035f4.0 -----slli ra, t5, 32 [ 764142] [==========================================================================f=====]-( 1279680000) 0x00800035f8.0 -----slli a4, s8, 32 [ 764143] [==========================================================================f=====]-( 1279680000) 0x00800035fc.0 -----addiw t0, a5, 2 [ 764144] [.............f..di...cr.........................................................]-( 1279760000) 0x0000000800.0 j pc + 0x3c [ 764145] [...............f.......di...cr..................................................]-( 1279760000) 0x000000083c.0 csrw dscratch, s0 [ 764146]
RISC-Vは通常命令領域は0x0080000000から始まるのだが、mulw
命令を実行後に突然0x0000000800
に飛んでいたりしている。これは何だろう?
それはともかく、現在のCoremarkの解析において気になっている部分を見てみよう。
load –> arith –> storeのループ
例えば、
loop lw a0, 0(a1) add a0, a0, 1 sw a0, 0(a3) ... bltz loop
みたいなループがある場合、swのメモリオーダを厳密に守ると、次のループのロードがswよりも先に出せず、パイプラインを活用することができない。 これはBOOMではどのように実行しているだろう。
例えばこういうループだな。lbuとsbに依存関係があって、次のループのlbuの実行を遅らせていると確実にパイプラインに影響があるのだが、BOOMではほとんど影響なくストールを生じさせていない。 このあたりは、ストアバッファの中を探索して、無関係なアドレスであれば先にロードを通すなどの処理が行われていると予想する。