2011年6月13日月曜日

ビットスワップ

TAOCP V4F0にはビット交換の技法がいろいろ書いてある. その大方の仕掛けはδスワップだが, TAOCPのベースのRISCマシン, MMIXにはMORとMXORという大形命令が存在し, それを巧みに利用する例題も多い.

これらの命令の説明はややこしく, なかなか覚えられないが, 今回のブログはその機能を覚えるためのものでもある.

MORはmultiple orのことで, 命令MOR $X, $Y, $Zは, 64ビットのレジスタ$Yと$Zのビットに演算を施し, レジスタ$Xに置くものである. TAOCP V1F1では,

m($X) ← m($Z)vxm($Y)

と説明する. レジスタ$Zと$Yの順が命令での順と逆なことに注意. この演算は, 64ビットレジスタをそれぞれ8ビットの行が縦に8行並んだ8 × 8の行列とみて, 2つの行列の乗算のような演算をするのである.

行列の乗算では, 積のi,j要素は, 被演算子の左の行列のi行と, 右の行列のj列の要素を次々と掛けて全体を足すのであった. それを2つの行列の間の演算+xで表わす.



今は要素は0か1である. それを次々と掛けて全体のor(v)を取るのである. MXOR命令は全体のxorを取る.

使い方の例として, TAOCPには
$Z = #0102040810204080
とすると, $Yのバイトの順が逆になるというのがある. つまり(abcdefgh)256が(hgfedcba)256になる. それを説明するのが, 次の図の上だ.



まず$Xの左上, X0,0は, $Zの0行目, 000...01と$Yの0列目のそれぞれを掛けるが, 1が最後にしかないので, ここに来るのはhのバイトの左端のビットである. その右隣りX0,1も, 同じ0行目と掛けるから, hのさっきのバイトの右隣りになる. 同様にした結果, $Xの0行目はhのバイトになる.

$Xの1行目は, $Zの1行目が000...10, つまり最後の1つ前にだけ1があるから, gの行が来る.

hの行が0行へ移った理由を再確認すると, Zの0行目の1が右端にあるからだ. つまり0行目へ置きたい$Yのバイトの位置を1にする. 赤矢印が0行目へ来るバイトの位置を示す.

そういう次第で, このパターンを使うと, $Yのバイトが逆転するのである.

下の図は左右逆転, つまりバイトの順は同じだが, バイトのビットを逆転する方法を示す. 上と同じで, $Xの0列目は, $Yの0列目の最後だけが1なので, hの各ビットが移動してきて, hになる. そして結局左からhgf...aと並ぶ.

ビット交換では, Yの0列の1の位置がXの0列に持ってきたいビットの位置である. (赤矢印)


これだけ分かると, V4F0にある完全シャッフルの問題(演習問題7.1.3-204)が解ける.

64ビットのレジスタzは

z = (x31...x1x0y31...y1y0)2

である. それを

w = (x31y31...x1y1x0y0)2

にしたい. ヒントがあって,

t = (x31x27x30x26x29x25x28x24y31y27y30y26y29y25y28y24...
    x7x3x6x2x5x1x4x0y7y3y6y2y5y1y4y0)2

u = (y27y31y26y30y25y29y24y28x27x31x26x30x25x29x24x28...
    y3y7y2y6y1y5y0y4x3x7x2x6x1x5x0x4)2

を中間結果とし, tとuを

MOR t,z,p; MOR t,q,t; MOR u,t,r; MOR u,r,u;

で作り,

PUT rM,m; MUX w,t,u;

とすると, 6命令で完全シャッフルが出来る. パターンp, q, r, mは何かという問題である.

このうちMUX命令は多重化マスクレジスタrMを見ながら, そのビットが1の所は$Yから, 0の所は$Zからデータを取る. PUT rM,mはパターンmをrMへ設定する命令だ. そうすると,

w31はx31にしたいからtから取る.
w30はy31にしたいからuから取る.
w29はx30にしたいからtから取る.
...
28まで行くと, 取るレジスタが交代する. 従って, 1010101001010101の繰り返しになるのだ. m = #aa55aa55aa55aa55


さて, zとtとの関係は, 次の図の上半分にある通り. バイトの交換とビットの交換をしている. 命令列の最初はMOR t,z,p;なので, $Zの方がパターンになり, バイトの交換だ. バイト位置の0,1,2,3,4,5,6,7に持ってきたいのは, それぞれ0,4,1,5,2,6,3,7だから, 下に示す行列のようになり, p = #8008400420021001でよかろう.



次の命令はパターンが$Yにあるから, ビット交換である. ビットの取り先は同じ関係だが, 縦と横が違うから転置のパターンにしなければならない.



q = #8020080240100401.

最後にtからuへの変換も, バイト交換とビット交換になっている. これはどちらも隣り同士の交換なので, パターンは同じである.

r = #4080102004080102.

TAOCPの演習問題には解答があるから覗いてみると, 正解であった.

0 件のコメント: