parfeval
並列プール ワーカーで関数を実行
説明
は、関数 F
= parfeval(fcn
,numout
,X1,...,Xm
)fcn
の実行をスケジュールします。使用可能な並列プールがある場合、MATLAB® はそれを使用してこの関数を実行します。それ以外の場合、この関数は逐次実行されます。
この構文を使用する並列コードは、Parallel Computing Toolbox™ を保有していない MATLAB ユーザーと共有できます。
MATLAB は、m
個の入力と n
個の出力を使い、関数 fcn
を非同期で [Y1,...,Yn] = fcn(X1,...,Xm)
として評価します。
MATLAB は、関数 fcn
の実行が完了する前に、Future
オブジェクト F
を返します。fetchOutputs
を使用すると、Future から結果 [Y1,...,Yn]
を取得できます。関数 fcn
の実行を停止するには、関数 cancel
を使用します。Future の詳細については、Future
を参照してください。
並列プールが開いている場合、MATLAB はその並列プールを使用して関数 fcn
を実行します。
並列プールが開いていない場合は、以下のようになります。
プールの自動作成が有効であれば、MATLAB は既定のクラスター プロファイルを使用して並列プールを開始し、その後その並列プールを使用して関数
fcn
を実行します。既定では、プールの自動作成は有効になっています。parpool
をプール引数pool
として指定することで、この動作を手動により強制できます。プールの自動作成が無効であれば、MATLAB は遅延実行を使用して関数
fcn
を実行します。parallel.Pool.empty
をプール引数pool
として指定することで、この動作を手動により強制できます。
例
parfeval
future のクエリおよびキャンセル
parfeval
または parfevalOnAll
を使用してバックグラウンドで計算を実行する際には、future と呼ばれるオブジェクトを作成します。future の State
プロパティを使用して、future が実行中か、待機中か、完了しているかを調べることができます。また、並列プールの FevalQueue
プロパティを使用して、実行中または待機中の future にアクセスすることもできます。future をキャンセルするには、関数 cancel
を使用できます。この例では、以下を行います。
cancel
を使用して future を直接キャンセルする。完了した future について完了エラーをチェックする。
FevalQueue
プロパティを使用して future にアクセスする。
キューへの作業の追加
2 つのワーカーをもつ並列プール p
を作成します。
p = parpool(2);
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to the parallel pool (number of workers: 2).
parfeval
を使用してバックグラウンドで計算を実行するときに、この関数は各計算について future を作成し、プールのキューに追加します。ワーカーがアイドルになるまで、タスクはキューに残ります。ワーカーがアイドルになると、キューが空でない場合はタスクの計算が開始されます。ワーカーがタスクを完了すると、タスクはキューから削除され、そのワーカーはアイドルになります。
parfeval
を使用して、ワーカーに関数 pause
を実行するように命令することにより、future の配列 f
を作成します。3 番目の future に引数 1
を使用し、その他すべての future に引数 Inf
を使用します。
for n = 1:5 if n == 3 f(n) = parfeval(@pause,0,1); else f(n) = parfeval(@pause,0,Inf); end end
parfeval
の使用ごとに、ワーカー上での関数の実行を表す future オブジェクトが返されます。3 番目の future を除く各 future は、計算に無限量の時間を要します。parfeval(@pause,0,Inf)
によって作成された future は、キューを低速化する future の極端な例です。
future の直接キャンセル
State
プロパティを使用して、future のステータスを取得できます。f
の各 future の状態からなる cell 配列を作成します。
{f.State}
ans = 1×5 cell
{'running'} {'running'} {'queued'} {'queued'} {'queued'}
3 番目を除く各タスクが永久に一時停止しています。
cancel
を使用して、2 番目の future を直接キャンセルします。
cancel(f(2)); {f.State}
ans = 1×5 cell
{'running'} {'finished'} {'running'} {'queued'} {'queued'}
2 番目の future をキャンセルすると、3 番目の future が実行されます。3 番目の future が完了するまで待ってから、再び状態を調べます。
wait(f(3)); {f.State}
ans = 1×5 cell
{'running'} {'finished'} {'finished'} {'running'} {'queued'}
3 番目の future の状態は 'finished'
になっています。
完了エラーのチェック
future が完了すると、その State
プロパティは 'finished'
になります。キャンセルされた future と正常に完了した future を区別するには、Error
プロパティを使用します。
fprintf("f(2): %s\n", f(2).Error.message)
f(2): Execution of the future was cancelled.
fprintf("f(3): %s\n", f(3).Error.message)
f(3):
message プロパティが示すように、コードは 2 番目の future をキャンセルします。message
プロパティで述べられているように、2 番目の future はキャンセルされました。3 番目の future はエラーなしで完了するため、エラー メッセージはありません。
プール キュー内の future のキャンセル
FevalQueue
プロパティを使用して、プール キュー内の future にアクセスできます。
p.FevalQueue
ans = FevalQueue with properties: Number Queued: 1 Number Running: 2
キューには RunningFutures
と QueuedFutures
の 2 つのプロパティがあります。RunningFutures
プロパティは、現在実行中のタスクに対応する future からなる配列です。
disp(p.FevalQueue.RunningFutures)
1x2 FevalFuture array: ID State FinishDateTime Function Error -------------------------------------------------------- 1 3 running @pause 2 6 running @pause
QueuedFutures
プロパティは、現在待機中で実行されていないタスクに対応する future からなる配列です。
disp(p.FevalQueue.QueuedFutures)
FevalFuture with properties: ID: 7 Function: @pause CreateDateTime: 08-Mar-2021 10:03:13 StartDateTime: RunningDuration: 0 days 0h 0m 0s State: queued Error: none
1 つの future、または future の配列をキャンセルできます。QueuedFutures
にあるすべての future をキャンセルします。
cancel(p.FevalQueue.QueuedFutures); {f.State}
ans = 1×5 cell
{'running'} {'finished'} {'finished'} {'running'} {'finished'}
RunningFutures
および QueuedFutures
は、f
が最新から最古へという順になっているかどうかにかかわらず、最新から最古へと並べ替えられます。各 future には、クライアントの有効期間に対する一意の ID
プロパティがあります。f
の各 future の ID
プロパティをチェックします。
disp(f)
1x5 FevalFuture array: ID State FinishDateTime Function Error -------------------------------------------------------------- 1 3 running @pause 2 4 finished (unread) 08-Mar-2021 10:03:20 @pause Error 3 5 finished (unread) 08-Mar-2021 10:03:21 @pause 4 6 running @pause 5 7 finished (unread) 08-Mar-2021 10:03:22 @pause Error
結果を、それぞれの RunningFutures
の ID
プロパティと比較します。
for j = 1:length(p.FevalQueue.RunningFutures) rf = p.FevalQueue.RunningFutures(j); fprintf("p.FevalQueue.RunningFutures(%i): ID = %i\n", j, rf.ID) end
p.FevalQueue.RunningFutures(1): ID = 3 p.FevalQueue.RunningFutures(2): ID = 6
ここで、RunningFutures
は f(1)
と f(4)
を含む配列です。RunningFutures(2)
をキャンセルすると、4 番目の future f(4)
がキャンセルされます。
場合によっては、ワークスペースで future を使用できないことがあります。たとえば、コードが完了する前に再び同じコードを実行する場合や、関数内で parfeval
を使用している場合などです。ワークスペースで使用できない future はキャンセルできます。
ワークスペースから f
をクリアします。
clear f
RunningFutures
と QueuedFutures
を使用して、未完了の future にアクセスできます。RunningFutures
を使用して f(4)
をキャンセルします。
rf2 = p.FevalQueue.RunningFutures(2); cancel(rf2) rf2.State
ans = 'finished'
まだキュー内にあるすべての future をキャンセルするには、次のコードを使用します。
cancel(p.FevalQueue.QueuedFutures); cancel(p.FevalQueue.RunningFutures);
関数を非同期的に実行して出力を取得
parfeval
を使用して、ワーカー上での関数の非同期実行を要求します。
たとえば、並列プールに 1 件の要求を投入します。fetchOutputs
を使用して出力を取得します。
f = parfeval(@magic,1,10); value = fetchOutputs(f);
また、for
ループに複数の Future 要求のベクトルを投入し、結果が使用可能になった時点で収集することもできます。効率性を高めるため、Future オブジェクトの配列を事前に割り当てます。
f(1:10) = parallel.FevalFuture; for idx = 1:10 f(idx) = parfeval(@magic,1,idx); end
fetchNext
を使用して、個々の Future 出力が使用可能になった時点で取得します。
magicResults = cell(1,10); for idx = 1:10 [completedIdx,value] = fetchNext(f); magicResults{completedIdx} = value; fprintf('Got result with index: %d.\n', completedIdx); end
parfeval
を使用したパラメーター スイープ中のプロット
この例では、並列パラメーター スイープを parfeval
により実行し、その結果を計算中に DataQueue
オブジェクトによって戻す方法を示します。
parfeval
は MATLAB をブロックしないため、計算の実行中に作業を続行できます。
この例では、ローレンツ常微分方程式系のパラメーター および に対してパラメーター スイープを実行し、この系のカオス的性質を説明します。
パラメーター グリッドの作成
パラメーター スイープで調べるパラメーターの範囲を定義します。
gridSize = 40; sigma = linspace(5, 45, gridSize); rho = linspace(50, 100, gridSize); beta = 8/3;
関数 meshgrid
を使用して、パラメーターの 2 次元グリッドを作成します。
[rho,sigma] = meshgrid(rho,sigma);
figure オブジェクトを作成し、'Visible'
を true
に設定すると、このオブジェクトがライブ スクリプトの外側の新しいウィンドウで開きます。パラメーター スイープの結果を可視化するには、表面プロットを作成します。表面の Z
要素を NaN
で初期化すると、空のプロットが作成されることに注意してください。
figure('Visible',true); surface = surf(rho,sigma,NaN(size(sigma))); xlabel('\rho','Interpreter','Tex') ylabel('\sigma','Interpreter','Tex')
並列環境の設定
関数 parpool
を使用して並列ワーカーのプールを作成します。
parpool;
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to the parallel pool (number of workers: 6).
ワーカーからデータを送信するには、DataQueue
オブジェクトを作成します。関数 afterEach
を使用して、ワーカーがデータを送信するたびに表面プロットを更新する関数を設定します。関数 updatePlot
は、この例の最後で定義するサポート関数です。
Q = parallel.pool.DataQueue; afterEach(Q,@(data) updatePlot(surface,data));
並列パラメーター スイープの実行
パラメーターを定義した後、並列パラメーター スイープを実行できます。
作業負荷を分散すると、parfeval
の効率性が向上します。作業負荷を分散するには、調べるパラメーターをグループ化して分割します。この例では、コロン演算子 (:
) を使用して、サイズを step
として均等に分割します。この結果得られる配列 partitions
には、分割の境界が含まれます。最後の分割の終点を追加しなければならないことに注意してください。
step = 100; partitions = [1:step:numel(sigma), numel(sigma)+1]
partitions = 1×17
1 101 201 301 401 501 601 701 801 901 1001 1101 1201 1301 1401 1501 1601
最良のパフォーマンスを得るには、次のように分割するようにします。
分割のスケジューリングのオーバーヘッドよりも計算時間が長くなる程度に大きい
すべてのワーカーをビジー状態に維持するために十分な分割数が存在する程度に小さい
並列ワーカーでの関数の実行を表し、その結果を保持するには、future オブジェクトを使用します。
f(1:numel(partitions)-1) = parallel.FevalFuture;
関数 parfeval
を使用して、計算を並列ワーカーにオフロードします。parameterSweep
はこのスクリプトの最後で定義されている補助関数で、調べるパラメーターの分割についてのローレンツ系を解きます。これには出力引数が 1 つあるため、parfeval
では出力の数として 1
を指定しなければなりません。
for ii = 1:numel(partitions)-1 f(ii) = parfeval(@parameterSweep,1,partitions(ii),partitions(ii+1),sigma,rho,beta,Q); end
parfeval
は MATLAB をブロックしないため、計算の実行中に作業を続行できます。ワーカーは並列で計算を実行し、中間結果を使用できるようになったら DataQueue
によって送信します。
parfeval
が完了するまで MATLAB をブロックする場合は、future オブジェクトに対して関数 wait
を使用します。この後のコードが parfeval
の完了に依存する場合、関数 wait
を使用すると便利です。
wait(f);
parfeval
が計算を完了すると、wait
は終了し、さらにコードを実行できるようになります。たとえば、結果として生成される表面の輪郭をプロットします。関数 fetchOutputs
を使用して、future オブジェクトに保存された結果を取得します。
results = reshape(fetchOutputs(f),gridSize,[]); contourf(rho,sigma,results) xlabel('\rho','Interpreter','Tex') ylabel('\sigma','Interpreter','Tex')
パラメーター スイープで計算リソースが多く必要で、クラスターにアクセス可能な場合は、parfeval
の計算をスケール アップできます。詳細については、デスクトップからクラスターへのスケール アップを参照してください。
補助関数の定義
調べるパラメーターの分割のローレンツ系を解く補助関数を定義します。DataQueue
オブジェクトで関数 send
を使用して、中間結果を MATLAB クライアントに送信します。
function results = parameterSweep(first,last,sigma,rho,beta,Q) results = zeros(last-first,1); for ii = first:last-1 lorenzSystem = @(t,a) [sigma(ii)*(a(2) - a(1)); a(1)*(rho(ii) - a(3)) - a(2); a(1)*a(2) - beta*a(3)]; [t,a] = ode45(lorenzSystem,[0 100],[1 1 1]); result = a(end,3); send(Q,[ii,result]); results(ii-first+1) = result; end end
新しいデータを受け取った時点で表面プロットを更新する別の補助関数を定義します。
function updatePlot(surface,data) surface.ZData(data(1)) = data(2); drawnow('limitrate'); end
afterEach
と afterAll
を使用したユーザー インターフェイスの非同期更新
この例では、計算の完了時にユーザー インターフェイスを更新する方法を説明します。parfeval
を使用して計算をワーカーにオフロードすると、ワーカーがこれらの計算を実行中にすべてのユーザー インターフェイスが応答可能な状態になります。この例では、waitbar
を使用して単純なユーザー インターフェイスを作成します。
それぞれの計算が完了するたびにユーザー インターフェイスを更新するには、
afterEach
を使用します。すべての計算が完了した後にユーザー インターフェイスを更新するには、
afterAll
を使用します。
waitbar
を使用して Figure ハンドル h
を作成します。afterEach
または afterAll
を使用すると、関数 waitbar
は Figure ハンドルを更新します。ハンドル オブジェクトの詳細については、ハンドル オブジェクトの動作を参照してください。
h = waitbar(0,'Waiting...');
parfeval
を使用して、乱数行列の固有値の実数部を計算します。parfeval
は、並列プールが作成されていなければ、自動的に既定の基本設定で作成します。
for idx = 1:100 f(idx) = parfeval(@(n) real(eig(randn(n))),1,5e2); end
afterEach
を使用して、parfeval
の各計算結果に対して自動的に関数を呼び出すことができます。各 future が完了するたびに、afterEach
を使用して各出力配列内の最大値を計算します。
maxFuture = afterEach(f,@max,1);
State
プロパティを使用して、future のステータスを取得できます。f
の future の State
プロパティが "finished"
である logical 配列を作成します。mean
を使用して、終了した future の割合を計算します。次に、無名関数 updateWaitbar
を作成します。関数は、h
のウェイト バーの割合の長さを、終了した future の割合に変更します。
updateWaitbar = @(~) waitbar(mean({f.State} == "finished"),h);
maxFuture
の各 future が完了するたびに、afterEach
と updateWaitbar
を使用してウェイト バーの割合の長さを更新します。すべての計算が完了したら、afterAll
と delete
を使用してウェイト バーを閉じます。
updateWaitbarFutures = afterEach(f,updateWaitbar,0); afterAll(updateWaitbarFutures,@(~) delete(h),0);
すべての future が完了したら、afterAll
と histogram
を使用して maxFuture
の結果のヒストグラムを表示します。
showsHistogramFuture = afterAll(maxFuture,@histogram,0);
入力引数
fcn
— 実行する関数
関数ハンドル
ワーカーで実行する関数。関数ハンドルとして指定します。
例: fcn = @sum
データ型: function_handle
numout
— 出力引数の数
非負の整数スカラー
出力引数の数。非負の整数スカラーとして指定します。
n
は fcn(X1,...,Xm)
の実行で想定される出力引数の数です。
データ型: single
| double
| int8
| int16
| int32
| int64
| uint8
| uint16
| uint32
| uint64
X1,...,Xm
— 入力引数
変数または式のコンマ区切りリスト
入力引数。変数または式のコンマ区切りリストとして指定します。
pool
— プール
parallel.Pool
オブジェクト
プール。parallel.Pool
オブジェクトとして指定します。
並列プールを作成するには、
parpool
を使用。バックグラウンド プールを取得するには、
backgroundPool
を使用。
例: parpool('Processes');
例: backgroundPool;
出力引数
F
— Future
parallel.FevalFuture
オブジェクト
拡張機能
自動並列サポート
Parallel Computing Toolbox™ を使用して自動的に並列計算を実行することで、コードを高速化します。
使用に関するメモと制限:
Parallel Computing Toolbox を保有している場合、構文
parfeval(fcn,n,X1,...,Xm)
では自動並列処理がサポートされます。
詳細については、自動並列サポートを使用した MATLAB 関数の実行を参照してください。
スレッドベースの環境
MATLAB® の backgroundPool
を使用してバックグラウンドでコードを実行するか、Parallel Computing Toolbox™ の ThreadPool
を使用してコードを高速化します。
この関数はスレッドベースの環境を完全にサポートします。詳細については、スレッドベースの環境での MATLAB 関数の実行を参照してください。
バージョン履歴
R2013b で導入R2021b: parfeval
はプールなしで逐次実行が可能
R2021b 以降、parfeval
はプールなしで逐次実行ができるようになりました。この動作により、作成した並列コードを、Parallel Computing Toolbox を保有していないユーザーと共有することができます。
構文 parfeval(fcn,n,X1,...,Xm)
を使用する際、Parallel Computing Toolbox があるならば、MATLAB は開いている並列プールの使用を試みます。並列プールが開いていない場合、プールの自動作成が有効であれば、MATLAB は並列プールを作成します。
並列プールの作成が無効になっている場合や Parallel Computing Toolbox を保有していない場合、関数は逐次評価されます。以前のリリースでは、MATLAB は代わりにエラーをスローしました。
参考
parfeval
| cancel
| ticBytes
| tocBytes
| afterEach
| afterAll
| fetchNext
| fetchOutputs
| parallel.pool.Constant
| parfevalOnAll
| parpool
| wait
| Future
MATLAB コマンド
次の MATLAB コマンドに対応するリンクがクリックされました。
コマンドを MATLAB コマンド ウィンドウに入力して実行してください。Web ブラウザーは MATLAB コマンドをサポートしていません。
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list:
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)