2

parfor ループでスクランブルされた準モンテカルロ数を生成する際に問題が発生しています。

問題は、parfor ループ内でこれらの数値のセットを複数生成すると、各セットの数値が同じになってしまうことです。以下に非常に簡単な例を示します。

D = 3;
M = 1000;
numbers = cell(1,4);

mystream = qrandstream(scramble(sobolset(D),'MatousekAffineOwen'));
myfun = @(x) qrand(mystream,x);

parfor i = 1:4
    numbers{i} = myfun(M);
end

この問題を示すために、このコードを実行した後、numbers{1}、numbers{2}、numbers{3}、numbers{4} の数字は次のように同じになります。

>>numbers{1}(1:3,:)
ans =
          0.76          0.05          0.77
          0.33          0.96          0.23
          0.60          0.72          0.52

>> numbers{2}(1:3,:)
ans =
          0.76          0.05          0.77
          0.33          0.96          0.23
          0.60          0.72          0.52

誰かがこの問題の修正を考えられるかどうか疑問に思っています。通常のランダムな数値ストリームを使用すると問題が発生しないため、何かできることがあるはずです。

準乱数ストリームの「スキップ」または「リープ」プロパティのようなものを悪用することはできません。その理由は、並列で実行するより大きな MATLAB プログラムで上記のコードのスニペットを使用しているためです...

4

1 に答える 1

4

各並列ワーカーでスクランブルするには、個別の呼び出しが必要です。これは、次のように qrandstream 関連のステートメントを parfor ループ内に移動することで実行できます。

D = 3;
M = 1000;
numbers = cell(1,4);

parfor i = 1:4
    mystream = qrandstream(scramble(sobolset(D),'MatousekAffineOwen'));
    myfun = @(x) qrand(mystream,x);

    numbers{i} = myfun(M);
end

理由: MatousekAffineOwen にはランダムなスクランブリング順序がありますが、MATLAB は準ランダム シーケンスを事前定義された巨大な配列として扱い、新しいサンプルが必要になるたびにサンプル データがその場で計算されます。スクランブルはこの順序を変更しますが、qrandstream オブジェクトは、スクランブルが呼び出されるとすぐに、一度発生したかのように動作します。その後、qrandstream は決定論的な数値のストリームです。非並列コード (または、最初に matlabpool を有効にせずに parfor を使用する場合) では、このセットアップは単一の qrandstream b/c で正常に機能します。MATLAB は、qrand への各呼び出しで (仮想) リストを処理し続けます。

しかし、parfor では、必要なすべての変数、関数などのコピーが各ワーカーに渡されます。その結果、各ワ​​ーカーは事前に定義された準乱数の重複したストリームを取得し、各ワーカーで同一のサンプル ストリームが生成されます。ちなみに、これはすべての数値 {i} が同じ値になるという意味ではありません。並列ワーカー (マシン コア) の数よりも大きな parfor ループ範囲の場合、複数のループ反復が同じワーカーで発生するため、反復しない同じ qrandstream を共有します。私の 2 コア マシンでは、4 反復のサンプル コードは、numbers{1}==numbers{4}と でこの動作を示します。numbers{2}==numbers{3}

于 2012-04-06T14:15:22.593 に答える