6

ループで多数の乱数を生成するプログラムを書いています。数値を予測しにくいものにしようとしています (セキュリティのためだけでなく、複数のスレッドでの衝突を避けるため)。

srand多くのドキュメントが、プログラム内で 1 回だけ呼び出すことを推奨していることに気付きました。例: C の乱数。選択された答えは、「原則として、プログラムで srand() を 1 回だけ呼び出す」です。

しかし、なぜ?このようなことをするのはなぜそんなに悪いのでしょうか:

int THIS_THREAD_SEED;
int randomness() {
    ++THIS_THREAD_SEED;
    int i;
    for(i=0 i<1000; i++) {
        unsigned n = rand_r(&THIS_THREAD_SEED) / RAND_MAX;
        /* do something with n */
    }
    return 0;
}

int do_something() {
    int i;
    for(i=0; i<1000; i++) {
        randomness();
    }
}

そのため、シードはプログラムごとではなく、関数呼び出しごとに 1 回変更されます。このように、実行中のスレッドの数に関係なく、2 つのスレッドがすべて同じ乱数リストを持つことはありません。

更新 各スレッドに一意のシードがあるか、競合状態を防ぐためにグローバル SEED にミューテックスがあるとします。

4

3 に答える 3

2

この質問を 2 つの別々の質問に分けましょう。

  1. 乱数ジェネレーターにアクセスするときに競合状態が心配な場合は、これを回避するためにミューテックスまたはその他の同期プリミティブを作成してください。

  2. 何度か電話することを考えている場合はsrand()、しないでください。この背後にある理由は、シードに基づいて変数を設定する乱数発生器の初期化ルーチンはランダム特性が悪く、乱数発生器自体よりもパフォーマンスが悪く、代用として使用すべきではないためです。

于 2012-11-26T01:36:28.543 に答える
1

srand()生成される数字のストリームをリセットrand()します。

srand のマニュアルから:

   The srand() function sets its argument as the seed for a  new  sequence
   of  pseudo-random  integers  to be returned by rand().  These sequences
   are repeatable by calling srand() with the same seed value.

「より良い」乱数が必要な場合は、 rand() が提供する乱数の他のソースを調べる必要があります。

また、srand()には使用されません。代わりにrand_r()( に) 指定した引数rand_r()が使用されます。

また、rand_r()複数のスレッドから使​​用する場合は、すべてのスレッドにローカル シードが必要です。そのために単一のグローバル変数を使用しないでください。

メルセンヌ・ツイスターrand()の代替品

しかし、「本当の」ランダム性が必要な場合は、ハードウェアのサポートを確認する必要があります。

そして答えるために:

そのため、シードはプログラムごとではなく、関数呼び出しごとに 1 回変更されます。このように、実行中のスレッドの数に関係なく、2 つのスレッドがすべて同じ乱数リストを持つことはありません。

いいえ、そのようには機能しません。スレッドごとに固有のものに初期化されたスレッドローカル SEED 変数が必要です。最初のシードに使用し、そのランダム シーケンスを使用して他のスレッドのシードを生成するか、または*nix を使用している場合time()は 4 ~ 8 バイトを読み取ることができます。/dev/random/dev/urandom

これは真夜中のランブルであるため、洞察を与えることを願っています。おやすみ<3

于 2012-11-26T01:36:56.197 に答える
0

競合状態を回避するには、スレッドごとに個別のシード変数を使用する必要があります。これは、各スレッドが独自の個別の乱数シーケンスを持つことを意味します。

于 2012-11-26T01:28:39.263 に答える