Hack the Cell 2009 反省会の反省
description
Transcript of Hack the Cell 2009 反省会の反省
![Page 1: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/1.jpg)
Hack the Cell 2009Hack the Cell 2009
反省会の反省反省会の反省
小寺春樹
口頭で説明した概要を に書いておきます。
![Page 2: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/2.jpg)
バイナリアン風味バイナリアン風味
Z80,68k,SH2,R3000,
R4300,ARM7,PowerPC※ なにはともあれ objdump
色々なCPUを使ってきました。Cellはまぁ、今回位では使った内には入らないですね。
![Page 3: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/3.jpg)
ビット転置ビット転置 ((スライス)実装スライス)実装基本的な事はおいておいて、変わってるところ
レジスタ幅を一杯に使って演算(実は致命傷)
623循環で組まなかった言い訳
![Page 4: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/4.jpg)
最初期の簡略化で思考固定化最初期の簡略化で思考固定化
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 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/5.jpg)
レジスタ幅をいっぱいに使わないと?レジスタ幅をいっぱいに使わないと?
処理単位はレジスタサイズの 128bit
状態空間サイズが 624(623+1)だと、端数が出る
処理単位毎の処理が均一じゃなくなる
ループ当たり処理要素数は少なくとも 624/640 にな
る。
コードサイズがでかくなる(後述)ビットスライス実装にしても 2^nの方がレジスタにはまるし、なんとなく効率良いと思っちゃってそれっきり。
![Page 6: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/6.jpg)
0 396 623
+1 +M
時間
状態空間更新のイメージ赤横線が読み出しで、計算して、青に書き込む感じ。
![Page 7: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/7.jpg)
0 396 623
+1 +M
時間
実際は矢印部分はレジスタで引き渡しますので、メモリのロード&ストアはライン当たり32ずつで済んでます。
![Page 8: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/8.jpg)
0 396 623
+1 +M
時間
に割り当てられるレジスタが1ライン毎に変わる -> コアループは偶数ラインで構成
![Page 9: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/9.jpg)
even/odd even/odd のバランス調整のバランス調整
基本的に evenが重いので、ステップ数増加を抑えつつodd側に振れる仕事を振っていきます。
![Page 10: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/10.jpg)
0 396 623
+1 +M
時間
+Mの値を取得するところ、2つのレジスタを結合して回す処理のところで調整を行います。
![Page 11: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/11.jpg)
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 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/12.jpg)
temperingtempering
temperingも一応考えました
![Page 13: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/13.jpg)
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 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/14.jpg)
(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 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/15.jpg)
(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 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/16.jpg)
(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 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/17.jpg)
コード生成(並び替え)コード生成(並び替え)
![Page 18: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/18.jpg)
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 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/19.jpg)
レジスタの動的割り当てによる再利用レジスタの動的割り当てによる再利用
参照完了直後に再利用。999ステップ目等は dual issue で参照完了と同時にターゲットになってたり。
![Page 20: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/20.jpg)
仕上げ仕上げ
![Page 21: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/21.jpg)
結果加算は結果加算は 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 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/22.jpg)
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 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/23.jpg)
その他その他
MT状態空間の 3/32をレジスタに常駐
連続メモリアクセスストールの回避
端数の処理も SIMD化している
1回限りのビット転置も高速化している
カウンタを oddパイプで実装
実行後のmtは問われないから、端数の処理を先にやる様にするとビット転置は1回で済んで楽ですよね。ん、そうでも
ない?
rotqbiiで 7bitカウンタを作る話
![Page 24: Hack the Cell 2009 反省会の反省](https://reader035.fdocument.pub/reader035/viewer/2022062808/5681525f550346895dc0927b/html5/thumbnails/24.jpg)
おしまいおしまい