Hack the Cell 2009 反省会の反省

24
Hack the Cell 2009 Hack the Cell 2009 反反反反反反 反反反反反反 反反反反 反反反反反反反反反反 反反反反反反反反

description

小寺春樹. Hack the Cell 2009 反省会の反省. に書いておきます。. 口頭で説明した概要を. バイナリアン風味. Z80,68k,SH2,R3000, R4300,ARM7,PowerPC. ※なにはともあれ objdump. 色々なCPUを使ってきました。 Cellはまぁ、今回位では使った内には入らないですね。. ビット転置(スライス)実装. 基本的な事はおいておいて、変わってるところ. レジスタ幅を一杯に使って演算(実は致命傷). 623循環で組まなかった言い訳. 最初期の簡略化で思考固定化. 状態空間を 2^n サイズにして、 - PowerPoint PPT Presentation

Transcript of Hack the Cell 2009 反省会の反省

Page 1: Hack the Cell 2009 反省会の反省

Hack the Cell 2009Hack the Cell 2009

反省会の反省反省会の反省

小寺春樹

口頭で説明した概要を に書いておきます。

Page 2: Hack the Cell 2009 反省会の反省

バイナリアン風味バイナリアン風味

Z80,68k,SH2,R3000,

R4300,ARM7,PowerPC※ なにはともあれ objdump

色々なCPUを使ってきました。Cellはまぁ、今回位では使った内には入らないですね。

Page 3: Hack the Cell 2009 反省会の反省

ビット転置ビット転置 ((スライス)実装スライス)実装基本的な事はおいておいて、変わってるところ

レジスタ幅を一杯に使って演算(実は致命傷)

623循環で組まなかった言い訳

Page 4: Hack the Cell 2009 反省会の反省

最初期の簡略化で思考固定化最初期の簡略化で思考固定化

mt 状態空間サイズは・ 624ワード以上の任意

・コアループ内の処理数もそれに応じて適当に変動

y = (mt[ idx & EN ]&UPPER_MASK) | (mt[ (idx+1)& EN ] & LOWER_MASK);

y = mt[ (idx+M)& EN ] ^ (y >> 1) ^ ((y&1)?MATRIX_A:0);

mt[ (idx+N)&EN ] = y;

状態空間を 2^n サイズにして、EN = 1023; // > N

インデクス計算時の mod 624 処理、 idx == N での比較分岐なりが削れる。

全部アンロールするとか考えてなかった時は、 2^nに状態空間拡張するのが単純でそこそこ速い。

Page 5: Hack the Cell 2009 反省会の反省

レジスタ幅をいっぱいに使わないと?レジスタ幅をいっぱいに使わないと?

処理単位はレジスタサイズの 128bit

状態空間サイズが 624(623+1)だと、端数が出る

処理単位毎の処理が均一じゃなくなる

ループ当たり処理要素数は少なくとも 624/640 にな

る。

コードサイズがでかくなる(後述)ビットスライス実装にしても 2^nの方がレジスタにはまるし、なんとなく効率良いと思っちゃってそれっきり。

Page 6: Hack the Cell 2009 反省会の反省

0 396 623

+1 +M

時間

状態空間更新のイメージ赤横線が読み出しで、計算して、青に書き込む感じ。

Page 7: Hack the Cell 2009 反省会の反省

0 396 623

+1 +M

時間

実際は矢印部分はレジスタで引き渡しますので、メモリのロード&ストアはライン当たり32ずつで済んでます。

Page 8: Hack the Cell 2009 反省会の反省

0 396 623

+1 +M

時間

に割り当てられるレジスタが1ライン毎に変わる -> コアループは偶数ラインで構成

Page 9: Hack the Cell 2009 反省会の反省

even/odd even/odd のバランス調整のバランス調整

基本的に evenが重いので、ステップ数増加を抑えつつodd側に振れる仕事を振っていきます。

Page 10: Hack the Cell 2009 反省会の反省

0 396 623

+1 +M

時間

+Mの値を取得するところ、2つのレジスタを結合して回す処理のところで調整を行います。

Page 11: Hack the Cell 2009 反省会の反省

A B

sel dst,A,B,mask

AB

rotqbyi dst,dst,#14rotqbii dst,dst,#4

A B

A B

AB

AB B

B B

A B

shufb dst,A,B,shufc1

rotqbii dst,dst,4

rotqbii tmp,B,4

shufb dst,dst,tmp,shufc2

=

even*1,odd*2 odd*4

even-1,odd+2となる代替処理の説明。なんとなく出来る事が分かって貰えればいいかなぁ。

Page 12: Hack the Cell 2009 反省会の反省

temperingtempering

temperingも一応考えました

Page 13: Hack the Cell 2009 反省会の反省

n=[]

def eor(a,b)

puts "(#{a}^#{b})"

"(#{a}^#{b})"

end

0.upto(31){|i| n[i]="n#{i}" }

31.downto(11){|i| n[i]=eor(n[i],n[i-11]) }

[0,3,4,5,7,10,12,13,17,19,21,22,24].each{|i| n[i] = eor(n[i],n[i+7]) }

[0,1,2,4,5,6,7,8,9,13,14].each{|i| n[i] = eor(n[i],n[i+15]) }

31.downto(18){|i| n[i] = eor(n[i],n[i-18]) }

こんな Rubyスクリプトを書いて、各ビットに元ビットがどう反映されているかを調べます。

Page 14: Hack the Cell 2009 反省会の反省

(n31^n20)

(n30^n19)

(n29^n18)

(n28^n17)

(n27^n16)

(n26^n15)

(n25^n14)

(n24^n13)

(n23^n12)

(n22^n11)

(n21^n10)

(n20^n9)

(n19^n8)

(n18^n7)

(n17^n6)

(n16^n5)

(n15^n4)

(n14^n3)

(n13^n2)

(n12^n1)

(n11^n0)

(n0^n7)

(n3^n10)

(n4^(n11^n0))

(n5^(n12^n1))

(n7^(n14^n3))

(n10^(n17^n6))

((n12^n1)^(n19^n8))

((n13^n2)^(n20^n9))

((n17^n6)^(n24^n13))

((n19^n8)^(n26^n15))

((n21^n10)^(n28^n17))

((n22^n11)^(n29^n18))

((n24^n13)^(n31^n20))

((n0^n7)^(n15^n4))

(n1^(n16^n5))

(n2^((n17^n6)^(n24^n13)))

((n4^(n11^n0))^((n19^n8)^(n26^n15)))

((n5^(n12^n1))^(n20^n9))

(n6^((n21^n10)^(n28^n17)))

((n7^(n14^n3))^((n22^n11)^(n29^n18)))

(n8^(n23^n12))

(n9^((n24^n13)^(n31^n20)))

(((n13^n2)^(n20^n9))^(n28^n17))

((n14^n3)^(n29^n18))

((n31^n20)^(((n13^n2)^(n20^n9))^(n28^n17)))

((n30^n19)^((n12^n1)^(n19^n8)))

((n29^n18)^(n11^n0))

((n28^n17)^(n10^(n17^n6)))

((n27^n16)^(n9^((n24^n13)^(n31^n20))))

((n26^n15)^(n8^(n23^n12)))

((n25^n14)^((n7^(n14^n3))^((n22^n11)^(n29^n18))))

(((n24^n13)^(n31^n20))^(n6^((n21^n10)^(n28^n17))))

((n23^n12)^((n5^(n12^n1))^(n20^n9)))

(((n22^n11)^(n29^n18))^((n4^(n11^n0))^((n19^n8)^(n26^n15))))

(((n21^n10)^(n28^n17))^(n3^n10))

((n20^n9)^(n2^((n17^n6)^(n24^n13))))

(((n19^n8)^(n26^n15))^(n1^(n16^n5)))

((n18^n7)^((n0^n7)^(n15^n4)))

出力はこんな感じ。一番左側がターゲットビット。

…これをよく睨むと

Page 15: Hack the Cell 2009 反省会の反省

(n31^n20)

(n30^n19)

(n29^n18)

(n28^n17)

(n27^n16)

(n26^n15)

(n25^n14)

(n24^n13)

(n23^n12)

(n22^n11)

(n21^n10)

(n20^n9)

(n19^n8)

(n18^n7)(n18^n7)

(n17^n6)

(n16^n5)

(n15^n4)

(n14^n3)

(n13^n2)

(n12^n1)

(n11^n0)

(n0^n7)(n0^n7)

(n3^n10)

(n4^(n11^n0))

(n5^(n12^n1))

(n7^(n14^n3))

(n10^(n17^n6))

((n12^n1)^(n19^n8))

((n13^n2)^(n20^n9))

((n17^n6)^(n24^n13))

((n19^n8)^(n26^n15))

((n21^n10)^(n28^n17))

((n22^n11)^(n29^n18))

((n24^n13)^(n31^n20))

((n0^n7)^(n15^n4))((n0^n7)^(n15^n4))

(n1^(n16^n5))

(n2^((n17^n6)^(n24^n13)))

((n4^(n11^n0))^((n19^n8)^(n26^n15)))

((n5^(n12^n1))^(n20^n9))

(n6^((n21^n10)^(n28^n17)))

((n7^(n14^n3))^((n22^n11)^(n29^n18)))

(n8^(n23^n12))

(n9^((n24^n13)^(n31^n20)))

(((n13^n2)^(n20^n9))^(n28^n17))

((n14^n3)^(n29^n18))

((n31^n20)^(((n13^n2)^(n20^n9))^(n28^n17)))

((n30^n19)^((n12^n1)^(n19^n8)))

((n29^n18)^(n11^n0))

((n28^n17)^(n10^(n17^n6)))

((n27^n16)^(n9^((n24^n13)^(n31^n20))))

((n26^n15)^(n8^(n23^n12)))

((n25^n14)^((n7^(n14^n3))^((n22^n11)^(n29^n18))))

(((n24^n13)^(n31^n20))^(n6^((n21^n10)^(n28^n17))))

((n23^n12)^((n5^(n12^n1))^(n20^n9)))

(((n22^n11)^(n29^n18))^((n4^(n11^n0))^((n19^n8)^(n26^n15))))

(((n21^n10)^(n28^n17))^(n3^n10))

((n20^n9)^(n2^((n17^n6)^(n24^n13))))

(((n19^n8)^(n26^n15))^(n1^(n16^n5)))

((n18^n7)^((n0^n7)^(n15^n4)))((n18^n7)^((n0^n7)^(n15^n4)))

この辺なんか無駄っぽい。 (n18^n7)は最後にしか出て来ないのに、n7は結局打ち消されてたり。

Page 16: Hack the Cell 2009 反省会の反省

(n31^n20)

(n30^n19)

(n29^n18)

(n28^n17)

(n27^n16)

(n26^n15)

(n25^n14)

(n24^n13)

(n23^n12)

(n22^n11)

(n21^n10)

(n20^n9)

(n19^n8)

(n18^n7)->x

(n17^n6)

(n16^n5)

(n15^n4)

(n14^n3)

(n13^n2)

(n12^n1)

(n11^n0)

(n0^n7)->x

(n3^n10)

(n4^(n11^n0))

(n5^(n12^n1))

(n7^(n14^n3))

(n10^(n17^n6))

((n12^n1)^(n19^n8))

((n13^n2)^(n20^n9))

((n17^n6)^(n24^n13))

((n19^n8)^(n26^n15))

((n21^n10)^(n28^n17))

((n22^n11)^(n29^n18))

((n24^n13)^(n31^n20))

((n0^n7)^(n15^n4)) -> (n0^(n15^n4)) (n0^(n15^n4)) , ((n0^(n15^n4))^n7)((n0^(n15^n4))^n7)

(n1^(n16^n5))

(n2^((n17^n6)^(n24^n13)))

((n4^(n11^n0))^((n19^n8)^(n26^n15)))

((n5^(n12^n1))^(n20^n9))

(n6^((n21^n10)^(n28^n17)))

((n7^(n14^n3))^((n22^n11)^(n29^n18)))

(n8^(n23^n12))

(n9^((n24^n13)^(n31^n20)))

(((n13^n2)^(n20^n9))^(n28^n17))

((n14^n3)^(n29^n18))

((n31^n20)^(((n13^n2)^(n20^n9))^(n28^n17)))

((n30^n19)^((n12^n1)^(n19^n8)))

((n29^n18)^(n11^n0))

((n28^n17)^(n10^(n17^n6)))

((n27^n16)^(n9^((n24^n13)^(n31^n20))))

((n26^n15)^(n8^(n23^n12)))

((n25^n14)^((n7^(n14^n3))^((n22^n11)^(n29^n18))))

(((n24^n13)^(n31^n20))^(n6^((n21^n10)^(n28^n17))))

((n23^n12)^((n5^(n12^n1))^(n20^n9)))

(((n22^n11)^(n29^n18))^((n4^(n11^n0))^((n19^n8)^(n26^n15))))

(((n21^n10)^(n28^n17))^(n3^n10))

((n20^n9)^(n2^((n17^n6)^(n24^n13))))

(((n19^n8)^(n26^n15))^(n1^(n16^n5)))

((n18^n7)^((n0^n7)^(n15^n4))) -> (n18^(n0^(n15^n4))) (n18^(n0^(n15^n4)))

こう変形すると、1ステップだけ減ります。これ以上減らないの?わかりません。

Page 17: Hack the Cell 2009 反省会の反省

コード生成(並び替え)コード生成(並び替え)

Page 18: Hack the Cell 2009 反省会の反省

e cntb $r14,$r14

e cntb $r30,$r30

e sumb $r14,$r30,$r14

r $r30

e cntb $r15,$r15

e cntb $r31,$r31

e sumb $r15,$r31,$r15

r $r31

o shufb $r0,$r0,$r8,shufc

r $r8

e a %0,%0,$r0

r $r0・発行順依存関係調べます・発行可能な中では単純に先着優先。あとはベースコード側の工夫でなんとかします。・ r っていうのはレジスタのリリース。まぁ、自動化するまでもないかなぁ、と。

Page 19: Hack the Cell 2009 反省会の反省

レジスタの動的割り当てによる再利用レジスタの動的割り当てによる再利用

参照完了直後に再利用。999ステップ目等は dual issue で参照完了と同時にターゲットになってたり。

Page 20: Hack the Cell 2009 反省会の反省

仕上げ仕上げ

Page 21: Hack the Cell 2009 反省会の反省

結果加算は結果加算は 88本の累積レジスタで処理本の累積レジスタで処理

0.upto(15){ |x|i = (x&1)*8+(x/2)@asm<<"e cntb $r#{i},$r#{i}"@asm<<"e cntb $r#{i+16},$r#{i+16}"@asm<<"e sumb $r#{i},$r#{i+16},$r#{i}"

}0.upto(7){|i|

@asm<<"o shufb $r#{i},$r#{i},$r#{i+8},shufc"@asm<<"e a %#{i},%#{i},$r#{i}"

}※shufc = {1,17,3,19, 5,21,7,23, 9,25,11,27, 13,29,15,31}

ライン当たりコストライン当たりコスト ::cntb*32, sumb*16, shufb*8, a*8cntb*32, sumb*16, shufb*8, a*8

even56,odd8と、合計ステップ数 64でも oddに 8振れているのがポイント

Page 22: Hack the Cell 2009 反省会の反省

cntb cnt

b

cntbcnt

b

sumb

sumb

shufbbit0,8,16,24

累積レジスタa

bit24bit8

bit16bit0

例)例) bit0,8,16,24bit0,8,16,24の集計の集計

+ +

+ +

※bit0 = MSB

8ビット間隔の重みのデータを cntb,sumb,shufbで組み上げる事で、SIMDワードとしてそのまま加算出来ますね、という話なのですがこれもあまり説明うまくなかったですね。

Page 23: Hack the Cell 2009 反省会の反省

その他その他

MT状態空間の 3/32をレジスタに常駐

連続メモリアクセスストールの回避

端数の処理も SIMD化している

1回限りのビット転置も高速化している

カウンタを oddパイプで実装

実行後のmtは問われないから、端数の処理を先にやる様にするとビット転置は1回で済んで楽ですよね。ん、そうでも

ない?

rotqbiiで 7bitカウンタを作る話

Page 24: Hack the Cell 2009 反省会の反省

おしまいおしまい