論文翻訳: Xorshift RNGs
George Marsaglia∗
The Florida State University
概要
Table of Contents
- ∗While the author is now Professor Emeritus, portions of the research for this article were done under by grants from The National Science Foundation.
1 導入
xorshift 乱数生成器 (xorshift RNG) は単純な計算構成である。コンピュータワードのシフト演算と排他的論理和 (xor) を繰り返し適用することによって
このような xorshift 操作を様々なシフト数や引数と組み合わせると、ランダム性テストで非常に良好となる非常に高速で単純な RNG を得ることができる。xorshift 操作の能力と有効性を理解するために、4 つの乱数シード x,y,z,w が与えられたとき、呼び出しごとに 3 つの xorshift 操作で
tmp = (x ˆ (x << 15));
x = y;
y = z;
z = w;
return w = (w ˆ (w >> 21)) ˆ (tmp ˆ (tmp >> 4));
このような手順は非常に高速で一般的に秒間 2 億回以上であり、結果のランダム整数はすべてのランダム性テスト、特に [3] の "タフ" テストと Diehard Battery [2] の新しいバージョンに合格している。
RNG がもたらすようなようなより長い周期を使用することもできるが、それらは整数の乗算と最新値を保存する (場合によっては大きくなる) テーブルを保持する必要がある。より詳細な比較は最後の要約セクションに記載している。
2 理論
ほとんどの RNG における数学的モデルは次の形式で記述できる:
xorshift RNG では、シード集合
2.1 すべての非ゼロバイナリベクトルを生成する行列
最初に [1] で与えられた主旨は以下の通り:
定理. 非特異
バイナリ行列 が非ゼロ初期 バイナリベクトル に対してシーケンス ですべての非ゼロ バイナリベクトルを生成するには、非特異 バイナリ行列の群において の次数が であることが必要かつ十分である。
証明. まず必要条件: もし
次に十分条件:
3 Xorshift RNG への適用
バイナリベクトル
ただし
| 1, 3,10| 1, 5,16| 1, 5,19| 1, 9,29| 1,11, 6| 1,11,16| 1,19, 3| 1,21,20| 1,27,27|
| 2, 5,15| 2, 5,21| 2, 7, 7| 2, 7, 9| 2, 7,25| 2, 9,15| 2,15,17| 2,15,25| 2,21, 9|
| 3, 1,14| 3, 3,26| 3, 3,28| 3, 3,29| 3, 5,20| 3, 5,22| 3, 5,25| 3, 7,29| 3,13, 7|
| 3,23,25| 3,25,24| 3,27,11| 4, 3,17| 4, 3,27| 4, 5,15| 5, 3,21| 5, 7,22| 5, 9,7 |
| 5, 9,28| 5, 9,31| 5,13, 6| 5,15,17| 5,17,13| 5,21,12| 5,27, 8| 5,27,21| 5,27,25|
| 5,27,28| 6, 1,11| 6, 3,17| 6,17, 9| 6,21, 7| 6,21,13| 7, 1, 9| 7, 1,18| 7, 1,25|
| 7,13,25| 7,17,21| 7,25,12| 7,25,20| 8, 7,23| 8,9,23 | 9, 5,1 | 9, 5,25| 9,11,19|
| 9,21,16|10, 9,21|10, 9,25|11, 7,12|11, 7,16|11,17,13|11,21,13|12, 9,23|13, 3,17|
|13, 3,27|13, 5,19|13,17,15|14, 1,15|14,13,15|15, 1,29|17,15,20|17,15,23|17,15,26|
要約すると、上記の 81 個のトリプル
yˆ=y<<a; yˆ=y>>b; yˆ=y<<c;
yˆ=y<<c; yˆ=y>>b; yˆ=y<<a;
yˆ=y>>a; yˆ=y<<b; yˆ=y>>c;
yˆ=y>>c; yˆ=y<<b; yˆ=y>>a;
yˆ=y<<a; yˆ=y<<c; yˆ=y>>b;
yˆ=y<<c; yˆ=y<<a; yˆ=y>>b;
yˆ=y>>a; yˆ=y>>c; yˆ=y<<b;
yˆ=y>>c; yˆ=y>>a; yˆ=y<<b;
64 ビット整数の場合、次数
| 1, 1,54| 1, 1,55| 1, 3,45| 1, 7, 9| 1, 7,44| 1, 7,46| 1, 9,50| 1,11,35| 1,11,50|
| 1,13,45| 1,15, 4| 1,15,63| 1,19, 6| 1,19,16| 1,23,14| 1,23,29| 1,29,34| 1,35, 5|
| 1,35,11| 1,35,34| 1,45,37| 1,51,13| 1,53, 3| 1,59,14| 2,13,23| 2,31,51| 2,31,53|
| 2,43,27| 2,47,49| 3, 1,11| 3, 5,21| 3,13,59| 3,21,31| 3,25,20| 3,25,31| 3,25,56|
| 3,29,40| 3,29,47| 3,29,49| 3,35,14| 3,37,17| 3,43, 4| 3,43, 6| 3,43,11| 3,51,16|
| 3,53, 7| 3,61,17| 3,61,26| 4, 7,19| 4, 9,13| 4,15,51| 4,15,53| 4,29,45| 4,29,49|
| 4,31,33| 4,35,15| 4,35,21| 4,37,11| 4,37,21| 4,41,19| 4,41,45| 4,43,21| 4,43,31|
| 4,53, 7| 5, 9,23| 5,11,54| 5,15,27| 5,17,11| 5,23,36| 5,33,29| 5,41,20| 5,45,16|
| 5,47,23| 5,53,20| 5,59,33| 5,59,35| 5,59,63| 6, 1,17| 6, 3,49| 6,17,47| 6,23,27|
| 6,27, 7| 6,43,21| 6,49,29| 6,55,17| 7, 5,41| 7, 5,47| 7, 5,55| 7, 7,20| 7, 9,38|
| 7,11,10| 7,11,35| 7,13,58| 7,19,17| 7,19,54| 7,23, 8| 7,25,58| 7,27,59| 7,33, 8|
| 7,41,40| 7,43,28| 7,51,24| 7,57,12| 8, 5,59| 8, 9,25| 8,13,25| 8,13,61| 8,15,21|
| 8,25,59| 8,29,19| 8,31,17| 8,37,21| 8,51,21| 9, 1,27| 9, 5,36| 9, 5,43| 9, 7,18|
| 9,19,18| 9,21,11| 9,21,20| 9,21,40| 9,23,57| 9,27,10| 9,29,12| 9,29,37| 9,37,31|
| 9,41,45|10, 7,33|10,27,59|10,53,13|11, 5,32|11, 5,34|11, 5,43|11, 5,45|11, 9,14|
|11, 9,34|11,13,40|11,15,37|11,23,42|11,23,56|11,25,48|11,27,26|11,29,14|11,31,18|
|11,53,23|12, 1,31|12, 3,13|12, 3,49|12, 7,13|12,11,47|12,25,27|12,39,49|12,43,19|
|13, 3,40|13, 3,53|13, 7,17|13, 9,15|13, 9,50|13,13,19|13,17,43|13,19,28|13,19,47|
|13,21,18|13,21,49|13,29,35|13,35,30|13,35,38|13,47,23|13,51,21|14,13,17|14,15,19|
|14,23,33|14,31,45|14,47,15|15, 1,19|15, 5,37|15,13,28|15,13,52|15,17,27|15,19,63|
|15,21,46|15,23,23|15,45,17|15,47,16|15,49,26|16, 5,17|16, 7,39|16,11,19|16,11,27|
|16,13,55|16,21,35|16,25,43|16,27,53|16,47,17|17,15,58|17,23,29|17,23,51|17,23,52|
|17,27,22|17,45,22|17,47,28|17,47,29|17,47,54|18, 1,25|18, 3,43|18,19,19|18,25,21|
|18,41,23|19, 7,36|19, 7,55|19,13,37|19,15,46|19,21,52|19,25,20|19,41,21|19,43,27|
|20, 1,31|20, 5,29|21, 1,27|21, 9,29|21,13,52|21,15,28|21,15,29|21,17,24|21,17,30|
|21,17,48|21,21,32|21,21,34|21,21,37|21,21,38|21,21,40|21,21,41|21,21,43|21,41,23|
|22, 3,39|23, 9,38|23, 9,48|23, 9,57|23,13,38|23,13,58|23,13,61|23,17,25|23,17,54|
|23,17,56|23,17,62|23,41,34|23,41,51|24, 9,35|24,11,29|24,25,25|24,31,35|25, 7,46|
|25, 7,49|25, 9,39|25,11,57|25,13,29|25,13,39|25,13,62|25,15,47|25,21,44|25,27,27|
|25,27,53|25,33,36|25,39,54|28, 9,55|28,11,53|29,27,37|31, 1,51|31,25,37|31,27,35|
|33,31,43|33,31,55|43,21,46|49,15,61|55, 9,56|
32 ビットの場合と同様に、64 ビットのシーケンスの場合は 275 個の
unsigned long xor(){
static unsigned long y = 2463534242;
y ˆ= (y << 13);
y = (y >> 17);
return (y ˆ= (y << 5));
}
個人的に気に入っている選択肢の一つである
64 ビット整数を持つ C コンパイラの場合、64 ビットシード
unsigned long long xor64(){
static unsigned long long x=88172645463325252LL;
x ˆ= (x << 13);
x ˆ= (x >> 7);
return (x ˆ= (x << 17));
}
ただし上記の 2200 個の選択肢のいずれかでも同様である。
3.1 次元のバイナリベクトル空間
32 次元のベクトル空間要素を表すために 32 ビットコンピュータワードを使用したり、64 ビット整数を許容するコンパイラで 64 次元を使用することは便利だが、より長い xorshift 周期を得るためにはより高い次元のベクトル空間要素を表す方法が必要である。これを行う良い方法は、例えば 32 ビット成分
自然な選択肢は
次に、例えば
// 2^64-1 周期
t = (x ˆ (x << a));
x = y;
return y = (y ˆ (y >> c)) ˆ (t ˆ (t >> b));
// 2^96−1 周期
t = (x ˆ (x << a));
x = y;
y = z;
return z = (z ˆ (z >> c)) ˆ (t ˆ (t >> b));
// 2^128−1 周期
t = (x ˆ (x << a));
x = y;
y = z;
z = w;
return w = (w ˆ (w >> c)) ˆ (t ˆ (t >> b));
これらの例はパラメータ [a,b,c] = [2,1,4], [7,13,6], [1,1,20] を選択して同じプロモーションスキームを使用して
t = (x ˆ (x >> a));
x = y;
y = z;
z = w;
w = v;
return v = (v ˆ (v >> c)) ˆ (t ˆ (t >> b));
必要に応じてブロックコンパニオン行列の最後の列を
// 2^96−1 周期
t = (x ˆ (x << 3)) ˆ (y ˆ (y >> 19)) ˆ (z ˆ (z << 6));
x = y;
y = z;
return (z = t);
// 2^128−1 周期
t = (x ˆ (x << 20)) ˆ (y ˆ (y >> 11)) ˆ (z ˆ (z << 27)) ˆ (w ˆ (w >> 6));
x = y;
y = z;
z = w;
return (w = t);
上記すべてのプロシジャは 32 ビット整数を返すが、プロシジャは
上の例では最後の値
unsigned long xorwow(){
static unsigned long x = 123456789, y = 362436069, z = 521288629,
w = 88675123, v = 5783321, d = 6615241;
unsigned long t;
t = (x ˆ (x >> 2));
x = y;
y = z;
z = w;
w = v;
v = (v ˆ (v << 4)) ˆ (t ˆ (t << 1));
return (d += 362437) + v;
}
シンプルで非常に高速 (1億2500万/秒)、
4 概要
xorshift 演算を様々な方法で組み合わせることによって単純で非常に高速な様々な RNG を開発することができるが、その単純性にもかかわらず生成される乱数はランダム性のタスとで非常に優れた特性を示している。上記で示した数百の
(multiply-with-carry; MWC) やキャリー付き相補乗算 (complimentary-multiply-with-carry) の方法は
ここで
unsigned long xor128(){
static unsigned long x = 123456789, y = 362436069, z = 521288629, w = 88675123;
unsigned long t;
t = (x ˆ (x << 11));
x = y;
y = z;
z = w;
return (w = (w ˆ (w >> 19)) ˆ (t ˆ (t >> 8)));
}
次にキャリー付き乗算 (MWC):
unsigned long mwc(){
static unsigned long x = 123456789, y = 362436069, z = 77465321, c = 13579;
unsigned long long t;
t = 916905990LL * x + c;
x = y;
y = z;
c = (t >> 32);
return z = (t & 0xffffffff);
}
MWC RNG は
どちらのルーチンも Diehard の一連のテスト [2] ですべて合格する。
どちらもほんの数個の C 命令を使うだけである。xorshift RNG は最新の 4 つの値を保持する必要がある。MWC は最新の 3 つとキャリー
xor128 のシード集合はいずれもゼロではない 4 つの 32 ビット整数 x,y,z,w だが、MWC のシード集合は 3 つの 32 ビット整数 x,y,z と初期 c<a である (x=y=z=c=0 と x=y=z=b-1 かつ c=a-1 の 2 つのケースを除く)。
しかし xor128() は mwc() よりはるかに高速である。1800MHz の PC では xor128() は 4.4 ナノ秒 (つまり秒間 2 億 2000 万回を超える) かかるが、mwc() は 21 ナノ秒 (秒間 4800 万回) を必要とする。ただし、当然のことながら乱数を必要とするシミュレーションの問題では秒間 4800 万回はボトルネックとは考えられない。
非常に長い周期を持つ RNG に関心がある場合は最大
References
- Marsaglia, George and Tsay, L. H., 1985, Matrices and the structure of random number sequences, Linear Algebra and its Applications, 67, 147–156.
- Marsaglia, George, 1995, The Marsaglia Random Number CDROM, with The Diehard Battery of Tests of Randomness, produced at Florida State University under a grant from The National Science Foundation. Access available at www.stat.fsu.edu/pub/diehard, and a revised version of the Diehard tests atwww.csis.hku.hk/˜diehard.
- Marsaglia, George and Tsang, Wai Wan, 2002, Some difficult-to-pass tests of randomness, Journal Statistical Software, 7, Issue 3.
- Marsaglia, George, 2003, Random number generators, Journal of Modern Applied Statistical Methods, 2 No. 2.
翻訳抄
ビット演算のみを使用した非常に高速でコンパクトな Xorshift 擬似乱数生成アルゴリズムに関する 2003 年の論文。著者はキャリー付き乗算の論文にも携わっている。Abstract にあるようにこの論文自体はアイディアの説明であり、良い乱数・悪い乱数で何点かの間違いが指摘されている。xoshiro+, xoroshiro** といったいくつかの改良アルゴリズムが開発されているため、実用目的であればそれらも参照。
- Marsaglia, 2003, Xorshift RNGs, Journal of Statistical Software Vol.8.
- Google Chromeが採用した、擬似乱数生成アルゴリズム「xorshift」の数理