yarv-dev:354
From: SASADA Koichi <ko1 atdot.net>
Date: Tue, 7 Dec 2004 09:50:42 +0900
Subject: [yarv-dev:354] Stack caching
ささだです。 スタックキャッシングを実装してみました。 2レベルのスタックキャッシュで次の状態を遷移しながら実行して いきます。 xx: キャッシュに乗っていない ax: レジスタ a にキャッシュとして乗っている bx: レジスタ b にキャッシュとして乗っている ab: レジスタ a, b にキャッシュとして乗っている b がトップ ba: レジスタ a, b にキャッシュとして乗っている a がトップ たとえば、ローカル変数を取得する命令 getlocal が、ax の状態 で実行されると、一個スタックを上に積むわけですから、ab の状態 に遷移します。取得したローカル変数の値はキャッシュレジスタ b に格納されます。 これも、命令記述から吐くようにしたんですが。VC の -O2g- では 非常に大きな効果を上げました。 しかし、gcc の -O2 や VC の -O2 では、遅くなりました。 今日もさっぱり理由がわかりません。というか、今日のほうがわか りません。 試したプログラムは次のとおりです。 i=0 while i<10000000 i+=1 end コンパイルすると、次のようになります。 0000 putobject_opopt_INT2FIX_OP_0_CP_ 0001 setlocal_opopt_2 0002 getlocal_opopt_2 0003 putobject 10000000 0005 opt_lt 0006 unless 14 0008 getlocal_opopt_2 0009 putobject_opopt_INT2FIX_OP_1_CP_ 0010 opt_plus 0011 setlocal_opopt_2 0012 jump 2 0014 putnil 0015 end 4 スタックキャッシュを有効にすると、次のようになります。 0000 putobject_opopt_INT2FIX_OP_0_CP__SC_xx_ax 0001 setlocal_opopt_2_SC_ax_xx 0002 getlocal_opopt_2_SC_xx_ax 0003 putobject_SC_ax_ab 10000000 0005 opt_lt_SC_ab_ax 0006 unless_SC_ax_xx 14 0008 getlocal_opopt_2_SC_xx_ax 0009 putobject_opopt_INT2FIX_OP_1_CP__SC_ax_ab 0010 opt_plus_SC_ab_ax 0011 setlocal_opopt_2_SC_ax_xx 0012 jump_SC_xx_xx 2 0014 putnil_SC_xx_ax 0015 end_SC_ax_xx 4 コンパイルした結果と見比べたりしてみましたが、スタックキャッ シュを有効にしたほうが、明らかに命令数が少ないのです。 例: gcc の出力したアセンブラ: putobject_SC_ax_ab # basic block 939 movl -296(%ebp), %ecx movl 4(%ecx), %eax # ax = operand(1) addl $8, %ecx # # movl %ecx, -296(%ebp) # pc += 8 movl %eax, -324(%ebp) # cache_regB = ax movl (%ecx), %eax # nextpc_ptr = *pc jmp *%eax # goto nextpc_ptr putobject # basic block 1309 movl -296(%ebp), %ecx # movl 4(%ecx), %eax # ax = operand(1) addl $8, %ecx # # movl %ecx, -296(%ebp) # pc store movl -300(%ebp), %ebx # # movl %eax, (%ebx) # *sp = ax addl $4, %ebx # # movl %ebx, -300(%ebp) # sp += 4 movl (%ecx), %eax # nextpc_ptr = *pc jmp *%eax # goto nextpc_ptr ちなみに、見てわかるとおり、キャッシュ用レジスタ変数はマシン レジスタではなく、スタック上に割り付けられています。 だいたい、どの命令もこんな感じで命令数が少ないのですが、なぜ か遅いです。(SC: スタックキャッシング) gcc => SC あり: 1.765000 SC なし: 1.640000 VC => SC あり: 1.016000 SC なし: 0.750000 (-Ox) VC が顕著に遅くなってます。 はて、なんででしょうか? ほんと全然見当が付きません。 あとは、Intel CPU のマイクロ命令への変換の過程でどうの、くら いしか思いつきません。つまり、利用するローカル変数が多いと Intel CPU は遅くなるとか? もしくは、ちょうどぴったりキャッシュラインが不幸にも一致して しまったとか、ちょうどぴったりベンチマーク時、システム全体の負 荷が SC 有効時に高かったりとか(ありえねー)。 ちなみに、「SC なし」とは、コンパイル時に SC 命令列に変換し ないだけで、VM のループの中には命令はぎっしり詰まっています。 だから、icache がどうの、とかは違うと思う。命令の並び順かなー とか考えて、並び替えてみたんですが、同様でしたし。 何か思いつく方いらっしゃいますか? -- // SASADA Koichi at atdot dot net // -- ML: yarv-dev quickml.atdot.net 使い方: http://www.atdot.net/~ko1/quickml
-> 354 2004-12-07 09:50 [ko1 atdot.net ] Stack caching 355 2004-12-07 10:10 ┣[ko1 atdot.net ] 356 2004-12-07 10:46 ┣[shudo computer.org ] 358 2004-12-07 13:43 ┃┗[ko1 atdot.net ] 357 2004-12-07 10:57 ┗[maeda-yarv atusi.org] 359 2004-12-07 13:52 ┗[ko1 atdot.net ]