スレッドセーフな一様乱数ジェネレーター
-
03-07-2019 - |
質問
各スレッドが同じ乱数列を生成する必要がある並列Fortran90コードがあります。
特定のシードについて、プログラムを実行するたびに同じ結果を繰り返すことができないため、スレッドセーフではないように見える乱数ジェネレータがあります。
スレッドセーフRNGのコードを探して(ほぼ)Web全体を検索できませんでした。誰かがそのコード(へのリンク)を提供してもらえますか?
事前に感謝します!
解決
Fortran90の擬似乱数ジェネレータは、 Intel Math Kernel Vector Statistics Library 。それらはスレッドセーフです。また、なぜスレッドセーフである必要があるのですか?各スレッドに同じリストを取得させたい場合は、同じシードを使用して各スレッドの新しいPRNGをインスタンス化します。
他のヒント
ほとんどの反復可能な乱数ジェネレーターには、何らかの形式の状態が必要です。国家がなければ、彼らは次に来ることをすることができません。スレッドセーフであるためには、自分で状態を保持する方法が必要です(つまり、グローバルにすることはできません)。
「同じ乱数列を生成する必要がある」と言うと、ということですか
- 各スレッドは、他のスレッドと同じ数値のストリームを生成する必要がありますか?これは、スレッドを剥離する前にシードを選択し、同じシードを使用して各スレッドでスレッドローカルPRNGをインスタンス化することを意味します。
または
- プログラムの異なる実行間で同じ数字のシーケンスを繰り返したいが、各スレッドは独自の独立したシーケンスを生成しますか?この場合、スレッド操作シーケンスは非決定的であるため、単一のPRNGを共有することはできません。そのため、スレッドを起動する前に既知のシードを使用して単一のPRNGをシードし、それを使用してスレッドの初期シードを生成します。 次に各スレッドでスレッドローカルジェネレータをインスタンス化します...
これらの各ケースでは、 Neil Butterworth 統計について言う:このように生成されたストリームをミックスする場合、PRNGが主張することを好むという通常の保証のほとんどは、信頼できない。
どちらの場合も、スレッドローカルPRNGが必要です。 f90で何が利用できるかわかりませんが、自分で書くこともできます(参照 Mersenne Twister 、保存された状態をパラメーターとして取るルーチンを作成します...)。
fortran 77では、これは次のようになります
function PRNGthread (state)
double state(statesize)
c stuff happens here which uses and manipulates the state vector...
PRNGthread = result
return
すべてのスレッドは同じ初期値を使用しますが、各スレッドは個別の状態ベクトルを維持する必要があります。
すべてのスレッドが同じ乱数のストリームを生成する必要があることを理解しています。
再現性のある数値ストリームを生成し、非常に高速な非常に優れた擬似ランダムジェネレーターは、 MT19937 。スレッドを生成する前にシードを生成することを確認しますが、すべてのスレッドでMTの個別のインスタンスを生成します(MTスレッドのインスタンスをローカルにします)。そうすれば、すべてのMTが同じ数のストリームを生成することが保証されます。
SPRNG はどうですか。自分で試したことはありません。
Mersenne Twister / MT19973のスレッドセーフFortran 90バージョンをコーディングしました。 PRNGの状態は派生型(randomNumberSequence)に保存され、プロシージャを使用してジェネレーターをシードするか、シーケンス内の次の要素を取得します。
選択肢は次のようです:
- 同期オブジェクト(次のような ミューテックス)ジェネレーターのシード 値。残念ながらこれは アクセス時にコードをシリアル化します ジェネレーター
- でスレッドローカルストレージを使用する 各スレッドが独自のスレッドを取得するためのジェネレーター シード-これは統計を引き起こす可能性があります アプリの問題
- プラットフォームが適切な アトミック操作、それを使用 シード(ただし、おそらくないでしょう)
非常に有望なリストではありません。それに追加するために、それらのどれをFORTRANで実装するかわからない!
この記事 https://www.cmiss.org/openCMISS/wiki/RandomNumberGenerationWithOpenMPは、Fortran実装にリンクするだけでなく、スレッドでPRNGを使用可能にするために必要なキーポイントについても言及しています。最も重要なポイントは次のとおりです。
ZigguratのFortran90バージョンには、 'SAVE'属性を持ついくつかの変数と配列があります。均一なRNGを並列化するために、必要な変更は、スレッドごとに個別の値を使用してこれらの変数配列を作成することであるようです(誤った共有に注意してください)。次に、PRNG関数が呼び出されると、スレッド番号を渡し、対応する状態値を使用する必要があります。