ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

乱数ストリームの制御

複数のワーカー

既定では、同じジョブを扱っているクラスター内の各ワーカーには独自の乱数ストリームがあります。次の例では、並列プールの 2 つのワーカーを使用して、それぞれが独自の乱数列を生成することを説明します。

p = parpool(2);
spmd
    R = rand(1,4); % Different on each worker
end
R{1},R{2}
    0.3246    0.6618    0.6349    0.6497

    0.2646    0.0968    0.5052    0.4866
delete(p)

すべてのワーカーで同じ数列を生成する必要がある場合は、各発生器をまったく同様にシードすることができます。

p = parpool(2);
spmd
    s = RandStream('twister'); % Default seed 0.
    RandStream.setGlobalStream(s);
    R = rand(1,4); % Same on all workers
end
R{1},R{2}
    0.8147    0.9058    0.1270    0.9134

    0.8147    0.9058    0.1270    0.9134
delete(p)

    メモ:   rng('shuffle') は現在の時刻に基づいて乱数発生器をシードするため、ストリームがそれぞれ独立するようにする場合は、このコマンドで複数のワーカーに乱数ストリームを設定しないようにしてください。特に、コマンドが複数のワーカーに同時に送信される場合 (parforspmd、通信ジョブの内部など) に注意が必要です。ワーカーでストリームが独立するようにするには、既定の動作を使用します。それでも不十分な場合は、ワーカーごとに固有のサブストリームを使用することを検討してください。

parfor ループ内で再現可能な一連の乱数を生成する方法についての詳細は、「parfor ループでの乱数の繰り返し」を参照してください。

クライアントとワーカー

MATLAB® ワーカーが MATLAB クライアントと同じマシンにあるローカル クラスターの一部であっても、既定では、クライアントとワーカーは異なる乱数発生器を使用します。クライアントでの既定値はメルセンヌ・ツイスター発生器 ('twister') で、ワーカーでの既定値は複数の再帰発生器の組み合わせ ('CombRecursive' または 'mrg32k3a') です。クライアントとワーカーで同じ数値のストリームを生成する必要がある場合は、一方のストリームを他方に一致させることができます。

たとえば、ワーカーでスクリプトをバッチ ジョブとして実行し、クライアントと同じ発生器または数列が必要であるとします。次の行を含む randScript1.m というスクリプト ファイルから開始します。

R = rand(1,4);

このスクリプトをクライアントで実行し、次に、ワーカーでバッチ ジョブとして実行できます。結果として生成される既定の乱数列が異なることに注意してください。

randScript1; % In client
R
R =
    0.8147    0.9058    0.1270    0.9134
parallel.defaultClusterProfile('local')
c = parcluster();
j = batch(c,'randScript1'); % On worker
wait(j);load(j);
R
R =
    0.3246    0.6618    0.6349    0.6497

同一の結果を得るために、同じ発生器とシードを使用するようクライアントとワーカーを設定できます。ここで、ファイル randScript2.m には次のコードが含まれているとします。

s = RandStream('CombRecursive','Seed',1);
RandStream.setGlobalStream(s);
R = rand(1,4);

続いて、この新しいスクリプトをクライアントとワーカーで実行します。

randScript2; % In client
R
R =
    0.4957    0.2243    0.2073    0.6823
j = batch(c,'randScript2'); % On worker
wait(j); load(j);
R
R =
    0.4957    0.2243    0.2073    0.6823

クライアントと GPU

既定では、MATLAB クライアントは GPU で実行されるコードとは異なる乱数発生器を使用します。GPU はこの点でワーカーと似ており、特に指定のない限り、複数の再帰発生器の組み合わせ ('CombRecursive' または 'mrg32k3a') を使用します。

次の例は、既定の乱数発生を、新しいセッションにおける CPU と GPU を比較して示しています。

Rc = rand(1,4)
Rc =
    0.8147    0.9058    0.1270    0.9134
Rg = rand(1,4,'gpuArray')
Rg =
    0.7270    0.4522    0.9387    0.2360

GPU は 3 種類の発生器 ('CombRecursive''Philox4x32-10''Threefry4x64-20') のみをサポートしています。次の表は、これらの発生器とそのプロパティのアルゴリズムの一覧です。

キーワード発生器複数のストリームとサブストリームのサポート高精度な場合の近似周期
'CombRecursive' または 'mrg32k3a'複数の再帰発生器の組み合わせあり2127
'Philox4x32-10'Philox 4x32 発生器、10 ラウンドあり2129
'Threefry4x64-20'Threefry 4x64 発生器、20 ラウンドあり2258

上記のいずれも、CPU ではクライアントの既定の発生器ではありません。CPU と GPU で同じ数列を生成するには、両方でサポートされている唯一の発生器 'CombRecursive' を使用しなければなりません。

sc = RandStream('CombRecursive','Seed',1);
RandStream.setGlobalStream(sc);
Rc = rand(1,4)
Rc =
    0.4957    0.2243    0.2073    0.6823
sg = parallel.gpu.RandStream('CombRecursive','Seed',1);
parallel.gpu.RandStream.setGlobalStream(sg);
Rg = rand(1,4,'gpuArray')
Rg =
    0.4957    0.2243    0.2073    0.6823

randn によって生成される正規分布乱数に対し、CPU コードでは既定で ZigguratNormalTransform 設定を使って乱数ストリームを使用しますが、GPU コードでは Inversion の設定を使用します。同じ randn 数列を取得するために、CPU 発生器と GPU 発生器を同じ設定にできます。GPU では Inversion しかサポートされないため、CPU をこれに一致するよう設定してください。

sc = RandStream('CombRecursive','NormalTransform','Inversion','Seed',1);
RandStream.setGlobalStream(sc)

sg = parallel.gpu.RandStream('CombRecursive','NormalTransform','Inversion','Seed',1);
parallel.gpu.RandStream.setGlobalStream(sg);

Rc = randn(1,4)
Rc =
   -0.0108   -0.7577   -0.8159    0.4742
Rg = randn(1,4,'gpuArray')
Rg =
   -0.0108   -0.7577   -0.8159    0.4742

ワーカー CPU とワーカー GPU

ワーカーの CPU で実行されるコードでは、ワーカーの GPU で実行されるコードと同じ発生器を使用して乱数を生成しますが、これらは同じストリームを共有しません。次の例に示すように、共通のシードを使用すると同じ数列を生成できます。この場合、各ワーカーは GPU と CPU で同じ数列を生成しますが、ワーカー間では数列が異なります。

p = parpool(2);
spmd
    sc = RandStream('CombRecursive','Seed',labindex);
    RandStream.setGlobalStream(sc);
    Rc = rand(1,4)

    sg = parallel.gpu.RandStream('CombRecursive','Seed',labindex);
    parallel.gpu.RandStream.setGlobalStream(sg);
    Rg = rand(1,4,'gpuArray')
end
delete(p)

randn によって生成される正規分布乱数に対し、ワーカー CPU では既定で ZigguratNormalTransform 設定を使いますが、ワーカー GPU では Inversion の設定を使用します。CPU と GPU で同じ数列が必要な場合は、両方で Inversion を使用するように設定できます。

この情報は役に立ちましたか?