自作MIPSプロセッサを作っている。4命令同時デコード、(理論上)4つの処理(演算、演算、分岐、メモリアクセス)を同時に実行可能なアウトオブオーダプロセッサだ (持っているSP605に入らないくらいでかい...)。
今日、いろいろバグを修正しながら性能測定をしていると、mips-2でコンパイルしたバイナリとmips-5でコンパイルしたバイナリで、mips-5でコンパイルしたバイナリの方がかなり遅くなっていた。(CMK値で1割くらい)。 命令数的には、mips-5の命令を使ったほうが命令数は1割くらい削減できることを確かめている。でも何故mips-5で実行したときに「命令数が少ない」のに「サイクル数」が増えてしまったのだろう?
実際にパイプラインログから解析してみた。ちょっと分かりにくいが、これは実際にどの命令がいつコミットされたかを示すグラフだ。
初見にはさっぱりだが、横軸がサイクル数、縦軸がコミットをおこした命令のPC値だと理解して頂きたい (ちなみ、命令キャッシュも分岐予測も現在積んでいないので、性能的にはひどい...)。 そして青色がMIPS-2、オレンジがMIPS-5でコンパイルしたバイナリだ。オレンジが少しずつ後ろに遅れていっているのが分かると思う。特に、最初の30,000サイクルから150,000サイクルあたりで顕著に遅れが発生している。 これはなんだろう?
という訳で拡大する (ちなみに、トータルで100万行くらいあるExcelシートのため、解析中にフリーズしまくって泣きそうになる...)。
なんだか良く分からない。オレンジ(mips-5)が青(mips-2)に比べて徐々に遅れている、くらいしか分からない。
とい訳で最終的にパイプラインダンプに焦点を当てる。
□ MIPS-2の場合:
| | | | | | (Cm53,D--)[PC=800009bc] : bnel r02,r00,0xfffb 020997|(Cm54,D58)[PC=800009c0] R03<=7f0001bc : lw r03,0x0004(r02)(25) 020998| | | | | | | (Cm55,D33)[PC=800009ac] R03<=00000001 : lh r03,0x0002(r03)(58) 020999| | (Cm56,D--)[PC=800009b0] : beq r03,r17,0x0008 021000|(Cm57,D42)[PC=800009b4] R07<=00000000 : addu r07,r00,r00 (49) 021001| (Cm58,D27)[PC=800009b8] R02<=7f000128 : lw r02,0x0000(r02)(53) 021002| | | | | | | | | | | | (Cm59,D--)[PC=800009bc] : bnel r02,r00,0xfffb 021003|(Cm60,D48)[PC=800009c0] R03<=7f0001b4 : lw r03,0x0004(r02)(33) 021004| | | | | | | (Cm61,D18)[PC=800009ac] R03<=00000003 : lh r03,0x0002(r03)(48) 021005| | (Cm62,D--)[PC=800009b0] : beq r03,r17,0x0008 021006|(Cm63,D11)[PC=800009b4] R07<=00000000 : addu r07,r00,r00 (42) 021007| (Cm00,D10)[PC=800009b8] R02<=7f000120 : lw r02,0x0000(r02)(27) 021008| | | | | | | | | | | | (Cm01,D--)[PC=800009bc] : bnel r02,r00,0xfffb 021009|(Cm02,D22)[PC=800009c0] R03<=7f0001b0 : lw r03,0x0004(r02)(18) 021010| | | | | | | (Cm03,D45)[PC=800009ac] R03<=00000004 : lh r03,0x0002(r03)(22) 021011| | (Cm04,D--)[PC=800009b0] : beq r03,r17,0x0008 021012|(Cm05,D29)[PC=800009b4] R07<=00000000 : addu r07,r00,r00 (11) 021013| (Cm06,D61)[PC=800009b8] R02<=7f000108 : lw r02,0x0000(r02)(10) 021014| | | | | | | | | | | | (Cm07,D--)[PC=800009bc] : bnel r02,r00,0xfffb 021015|(Cm08,D36)[PC=800009c0] R03<=7f0001a4 : lw r03,0x0004(r02)(45) 021016| | |
□ MIPS-5の場合:
(Cm45,D18)[PC=80000478] R02<=7f000130 : lw r02,0x0000(r02)(35) 019502| | (Cm46,D--)[PC=8000047c] : bne r02,r00,0xfffa 019503|(Cm47,D--)[PC=80000480] : sll r00,r00,r00 019504| | | ---------- FLUSH --------------- FLUSH -------------- FLUSH --------------- FLUSH -------------- FLUSH | | | | | | | | | | | | | | | | | | | | | | (Cm48,D54)[PC=80000468] R03<=7f0001b8 : lw r03,0x0004(r02)(26) 019505| | | | | | | | (Cm49,D04)[PC=8000046c] R03<=00000002 : lh r03,0x0002(r03)(54) 019506| | (Cm50,D--)[PC=80000470] : beq r03,r04,0x0016 019507|(Cm51,D--)[PC=80000474] : sll r00,r00,r00 019508| (Cm52,D40)[PC=80000478] R02<=7f000108 : lw r02,0x0000(r02)(18) 019509| | | | | | (Cm53,D--)[PC=8000047c] : bne r02,r00,0xfffa 019510|(Cm54,D--)[PC=80000480] : sll r00,r00,r00 019511| | | ---------- FLUSH --------------- FLUSH -------------- FLUSH --------------- FLUSH -------------- FLUSH | | | | | | | | | |
実はbne命令が、
命令となっている。これにより、分岐予測を持たない現在のコアでは、bnelを使ったほうがパイプラインフラッシュが発生しないため、有利に働いているのだ。 では、何故mips-5ではlikely命令が出ないかというと、おそらく実装の容易性だと思われる。bnel命令とbne命令が混在すると、likely用に特殊な実装しなくてはならないため、HWが複雑になる。 これを防ぐためにbneを使っているものと思われるが、つまるところ早く分岐予測を実装しろ、ということか。がんばります。。。