擬似乱数ジェネレータのためのクラスター環境
-
28-10-2019 - |
質問
かを独立した擬似乱数、クラスター、モンテカルロシミュレーション。できる多くの計算ノード(例:100)を生成しなければならない単位百万番号は各ノードです。ったものを保証するPRN配列を一つのノードが重なり合わないのPRN配列を他のノードです。
- 私がすべてのPRNにルートノード、送信して他のノード。ているのは、あまりにも遅くなります。
- 私はジャンプを知距離の配列は、各ノードです。があるようなアルゴリズムのメルセンヌ-ツイスターまたはその他のPRNG、できるために合理的に必要十分な時間やメモリ?
- 使ってみました異なる発電機などの各ノードです。ができるの良い発電機のようなメルセンヌ-ツイスター?どうすればいすることはできますか。
- その他のもの?
解決
同じ元のストリームから取得した潜在的に重複するランダムストリームを使用しないでください。結果として生じるインターリーブストリームをテストしていない場合、その統計的品質についてはわかりません。
幸運、 Mersenne Twister(MT) 配布タスクに役立ちます。呼び出された専用アルゴリズムを使用します ダイナミックな作成者 (以下DC)、作成できます 独立した乱数ジェネレーター これにより、非常に独立したランダムストリームが生成されます。
各ストリームは、それを使用するノードに作成されます。基本的に、DCはMTの異なるインスタンスを作成するオブジェクト指向パラダイムのコンストラクターと考えてください。それぞれの異なるインスタンスは、非常に独立したランダムシーケンスを生成するように設計されています。
ここでDCを見つけることができます: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/mt/dc/dc.html
使用するのは非常に簡単で、取得するさまざまなMTインスタンスの数やこれらのMTの期間など、さまざまなパラメーターを修正できます。入力パラメーターに応じて、DCはランタイムが変更されます。
DCと一緒に付属するREADMEに加えて、ファイルをご覧ください example/new_example2.c
DCアーカイブで。独立したシーケンスを取得するための呼び出しの例を示しています 別の入力識別子が与えられた, 、基本的にはクラスタージョブを特定するために必要なものです。
最後に、並列または分散環境でPRNGを使用する方法について詳しく知るつもりなら、この科学記事を読むことをお勧めします。
確率的高性能コンピューティングのためのランダムストリームの実用的な分布, 、David RC Hill、In 高性能コンピューティングとシミュレーションに関する国際会議(HPCS), 2010
他のヒント
さて、答え#2 ;-)
私は言うつもりです...それをシンプルにしてください。 「短い」種子を使用してMTをプライミングするだけです(この種が2であると想像してください32 より良い制限がないためのビット)。これは、短い種子が「十分に分布した」MT開始状態を生成することを前提としています(例: init_genrand
私の他の答えのコードでは、うまくいけば)。これは、均等に分散された開始状態を保証するものではなく、「十分な」ということを保証するものではありません。以下を参照してください。
各ノードは、事前に選択されたシードの独自のシーケンスを使用します(送信されるランダムシードのリストまたは式 number_nodes * node_number * iteration
)。重要なことは、最初の「短い」種子が ノード全体で再利用されることはありません.
各ノードは、このシードで初期化されたMT PRNGを使用します n
時代 n <<< MT_period / max_value_of_short_seed
(TT800は2です800-1およびMT19937は2です19937-1, 、 それで n
まだです 非常に大きい 番号)。後 n
時間、ノードは選択したリストの次のシードに移動します。
私は、ノードが同時に(またはまったく)重複したシーケンスを持つことはないという「保証」を提供しませんが(またはまったく)、ここに何がありますか AMDは、さまざまなシードの使用について述べています: :(明らかに、最初のシードアルゴリズムが役割を果たします)。
ここで説明する複数のストリームを作成するための4つの方法のうち、これは最も満足のいくものではありません ...たとえば、初期値が十分に離れていない場合、異なる開始点から生成されたシーケンスが重複する場合があります。使用されている発電機の周期が大きい場合、オーバーラップシーケンスの可能性が減少します。 シーケンスの独立性を保証するものはありませんが、非常に大きな期間のために、ランダム開始値を持つMersenne Twisterを使用することは問題につながる可能性は低いです, 、特に必要なシーケンスの数が小さい場合...
ハッピーコーディング。
各ノードで、シーケンス内の既知の距離にジャンプすることができました。しかし、Mersenne-Twisterまたは他の優れたPRNGにはそのようなアルゴリズムがありますか?
はい、参照してください http://theo.phys.sci.hiroshima-u.ac.jp/abishikawa/prng/mt_stream_en.html. 。これは、独立した乱数ストリームを取得するための優れたソリューションです。各ストリームから必要な乱数の数よりも大きいジャンプを作成して、各ストリームの開始を作成することにより、ストリームは重複しません。
免責事項:までお問い合わせください保証MTのサイクル重合開始から任意の"uint"(またはxほど強いものではありませんで任意のものの独自の価値)種子、それを見てがある場合は保証をするのに十分なだけの開始は各ノードとは別の"uint"種は、このポストが大きく議論の余地がある問題.(のサイクルの長期間のMTです 驚異的な 割出UINT_MAX残る 理解 --以外の紙に--。)
でも、ここが私のコメントへの答えは...
私のようなアプローチ#2かじめ生成されていたセットの状態富士山の各ノードは初期化された開始。
のみ、初期状態は維持されなければならなはもちろんのこと、これらが発生するこれらの国で
- 再使用を無期限が要件を満たした場合、または;
- 次の状態で発生する前に、外部の高速ボックスのシミュレーションやランニング;
- のノードできる報告を終了状態の場合の信頼性グループ-プレゼンテーションおよび配列の場合は同一料金の中でノードとしての要件等)
ことを考慮することができ 高速生成, いますのでおすすめできません#3上からとしても複雑で、多数の文字列を付属します。オプション#1な簡単なものでない場合があ力十分です。
オプション#2のように非常に良い。のサーバーの"高速機"、というわけではありませんのノード)を送信開始時の状態には次の"未使用の配列ブロック"(例えば、億サイクル)のノードを利用する発電機が一億サイクルのお問い合わせいただく前に新しいブロックです。このということなのでハイブリッドの#1の非常に少しています。
自分のシステム、Core2Duoまで 一億円 乱数17秒用のコードは以下の通りで運行 LINQPad).までお問い合わせくださいMT variantことです。
void Main()
{
var mt = new MersenneTwister();
var start = DateTime.UtcNow;
var ct = 1000000000;
int n = 0;
for (var i = 0; i < ct; i++) {
n = mt.genrand_int32();
}
var end = DateTime.UtcNow;
(end - start).TotalSeconds.Dump();
}
// From ... and modified (stripped) to work in LINQPad.
// http://mathnet-numerics.googlecode.com/svn-history/r190/trunk/src/Numerics/Random/MersenneTwister.cs
// See link for license and copyright information.
public class MersenneTwister
{
private const uint _lower_mask = 0x7fffffff;
private const int _m = 397;
private const uint _matrix_a = 0x9908b0df;
private const int _n = 624;
private const double _reciprocal = 1.0/4294967295.0;
private const uint _upper_mask = 0x80000000;
private static readonly uint[] _mag01 = {0x0U, _matrix_a};
private readonly uint[] _mt = new uint[624];
private int mti = _n + 1;
public MersenneTwister() : this((int) DateTime.Now.Ticks)
{
}
public MersenneTwister(int seed)
{
init_genrand((uint)seed);
}
private void init_genrand(uint s)
{
_mt[0] = s & 0xffffffff;
for (mti = 1; mti < _n; mti++)
{
_mt[mti] = (1812433253*(_mt[mti - 1] ^ (_mt[mti - 1] >> 30)) + (uint) mti);
_mt[mti] &= 0xffffffff;
}
}
public uint genrand_int32()
{
uint y;
if (mti >= _n)
{
int kk;
if (mti == _n + 1) /* if init_genrand() has not been called, */
init_genrand(5489); /* a default initial seed is used */
for (kk = 0; kk < _n - _m; kk++)
{
y = (_mt[kk] & _upper_mask) | (_mt[kk + 1] & _lower_mask);
_mt[kk] = _mt[kk + _m] ^ (y >> 1) ^ _mag01[y & 0x1];
}
for (; kk < _n - 1; kk++)
{
y = (_mt[kk] & _upper_mask) | (_mt[kk + 1] & _lower_mask);
_mt[kk] = _mt[kk + (_m - _n)] ^ (y >> 1) ^ _mag01[y & 0x1];
}
y = (_mt[_n - 1] & _upper_mask) | (_mt[0] & _lower_mask);
_mt[_n - 1] = _mt[_m - 1] ^ (y >> 1) ^ _mag01[y & 0x1];
mti = 0;
}
y = _mt[mti++];
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680;
y ^= (y << 15) & 0xefc60000;
y ^= (y >> 18);
return y;
}
}
嬉しい符号といいます。
TRNGは、並列クラスター環境を念頭に置いて特別に構築された乱数ジェネレーターです(具体的にはドイツのティナスーパーコンピューター向けに構築されました)。したがって、独立した乱数ストリームを作成し、非標準分布を生成することも非常に簡単です。ここに設定する方法に関するチュートリアルがあります:http://www.lindonslog.com/programming/parallel-random-number-generation-trng/