乱数

以前SPUで乱数を使うためにメルセンヌツイスターを実装した.
この時はただコードを書いただけで全く効率化していないものだったので,少し調べてみたらMMXを使用したSFMTというものがあるそうで,速いらしいとソースコードをダウンロードしてみた.
しかし驚いた事にメモリの使用量が半端ではなく,とてもSPUで使う気にはならなかった.

そこでSPUに適した擬似乱数発生関数としてXorShiftというものがあるということが分かったので,このSPU版を作成した.
MTと違ってXorShiftはここに全て書くこともできるほどコンパクトだ.


vector unsigned int xor128() {
static vector unsigned int x = (vector unsigned int){1914768229,1813631753,1066933042,123456789};
static vector unsigned int y = (vector unsigned int){1924991794,322169939,401805720,362436069};
static vector unsigned int z = (vector unsigned int){676781941,650659395,136964893,521288629};
static vector unsigned int w = (vector unsigned int){1450727136,97311992,63449669,88675123};
vector unsigned int t;
t = spu_xor( x, spu_sl( x, 11 ) );
x = y;
y = z;
z = w;
w = spu_xor( spu_xor( w, spu_rlmask( w, -19 ) ), spu_xor( t, spu_rlmask( t, -8 ) ) );
return w;
}
この関数は1E9の乱数発生に3.139secかかるが,これは上記のサイトのCore 2 Duoと同程度の速度だが,一度に128bitの乱数が得られるので,使い方によってはその4倍の効率 とも言える.