ワーカー上の乱数ストリームの制御
並列計算において、乱数発生関数 rand
、randi
および randn
の動作は MATLAB® クライアントと異なります。並列ワーカー上またはクライアント上の乱数発生器の動作を変更して、再現可能な乱数ストリームを生成することができます。
MATLAB ワーカーが MATLAB クライアントと同じマシンにあるローカル クラスターの一部であっても、既定でクライアントとワーカーは異なる乱数発生器を使用します。次の表は、クライアントおよびワーカーの既定の設定をまとめています。
発生器 | シード | 正規変換 | |
---|---|---|---|
クライアント | 'Twister' または 'mt19937ar' | 0 | 'Ziggurat' |
ワーカー (ローカルまたはリモート) | 'Threefry' または 'Threefry4x64_20' | 0 | 'Inversion' |
使用可能な発生器および正規変換の詳細については、乱数発生器の選択を参照してください。クラスター内の各ワーカーは、表内のプロパティを使用して、独立したストリームから乱数を取得します。既定で、parfor
ループ内で各ワーカー上に生成される乱数は相互に異なり、クライアント上で生成される乱数とも異なります。
メモ
ワーカー上に GPU がある場合、GPU の乱数ストリームには異なる設定が適用されます。詳細については、GPU 上の乱数ストリームを参照してください。
クライアントとワーカー
クライアントとワーカーで同じ数値のストリームを生成する必要がある場合は、一方のストリームを他方に一致させることができます。rng
を使用して、発生器アルゴリズムおよびシードを設定できます。
たとえば、ワーカーでスクリプトをバッチ ジョブとして実行し、クライアントと同じ発生器または数列が必要であるとします。次の行を含む randScript1.m
というスクリプト ファイルから開始します。
R = rand(1,4);
このスクリプトをクライアントで実行し、次に、ワーカーでバッチ ジョブとして実行できます。結果として生成される既定の乱数列が異なることに注意してください。
randScript1; % In client
R
R = 0.8147 0.9058 0.1270 0.9134
parallel.defaultClusterProfile('Processes') c = parcluster(); j = batch(c,'randScript1'); % On worker wait(j);load(j); R
R = 0.1349 0.6744 0.9301 0.5332
同一の結果を得るために、同じ発生器とシードを使用するようクライアントとワーカーを設定できます。ここで、ファイル randScript2.m
には次のコードが含まれているとします。
rng(1,'Threefry');
R = rand(1,4);
続いて、この新しいスクリプトをクライアントとワーカーで実行します。
randScript2; % In client
R
R = 0.1404 0.8197 0.1073 0.4131
j = batch(c,'randScript2'); % On worker wait(j); load(j); R
R = 0.1404 0.8197 0.1073 0.4131
クライアントおよびワーカーで乱数発生器の設定を既定値にリセットするには、このコードを randScript2.m
の末尾に追加します。
rng('default')
複数のワーカー
既定では、同じジョブを処理するクラスター内の各ワーカーに、独立した乱数ストリームがあります。rand
、randi
または randn
が並列で呼び出される場合、各ワーカーは独自の乱数列を生成します。
メモ
rng('shuffle')
は現在の時刻に基づいて乱数発生器のシードを設定するため、確実に各ストリームを独立にする場合は、このコマンドを使用して複数のワーカーに乱数ストリームを設定しないでください。特に、コマンドが複数のワーカーに同時に送信される場合 (parfor
、spmd
、通信ジョブの内部など) に注意が必要です。ワーカー上のストリームを独立にするには、既定の動作を使用します。それでもニーズが満たされない場合は、RandStream
を使用して、各ワーカーで独自のサブストリームを使用することを検討してください。
次の例では、並列プールの 2 つのワーカーを使用して、それぞれが独自の乱数列を生成することを説明します。
p = parpool(2); spmd R = rand(1,4); % Different on each worker end R{1},R{2}
ans = 0.1349 0.6744 0.9301 0.5332 ans = 0.6383 0.5195 0.1398 0.6509
delete(p)
すべてのワーカーで同じ数列を生成させる必要がある場合、同じ発生器の設定を使用するように各ワーカーを設定できます。
p = parpool(2); spmd rng(0,'Philox'); % Default seed 0. R = rand(1,4); % Same on all workers end R{1},R{2}
ans = 0.3655 0.6975 0.1789 0.4549 ans = 0.3655 0.6975 0.1789 0.4549
delete(p)
parfor
ループの反復ごとに乱数を制御する必要がある場合は、parfor ループでの乱数の繰り返しを参照してください。
正規分布乱数
関数 randn
を使用して正規分布乱数を扱う場合、RandStream
を使用して、各ワーカーおよびクライアントの発生器タイプ、シードおよび正規変換アルゴリズムを設定することで、前述した同じ方法を使用できます。
たとえば、ファイル randScript3.m
に次のコードが含まれているとします。
stream = RandStream('Threefry','Seed',0,'NormalTransform','Inversion'); RandStream.setGlobalStream(stream); R = randn(1,7)
batch
または spmd
を使用) 、同じ乱数列を生成できます。R = -0.3479 0.1057 0.3969 0.6544 -1.8228 0.9587 0.5360