afterEach
と afterAll
を使用したコールバック関数の実行
parfeval
、parfevalOnAll
、afterEach
、または afterAll
を使用してバックグラウンドまたは並列プールで関数を実行する際には、Future
を作成します。afterEach
と afterAll
を使用すると、1 つ以上の Future
オブジェクトが終了した後に自動でコールバック関数を実行することができます。
afterEach
を使用する場合、MATLAB® は各Future
オブジェクトの終了後にコールバック関数を実行します。Future
の配列にM
個の要素がある場合、MATLAB クライアントはコールバック関数をM
回実行します。afterAll
を使用する場合、MATLAB はすべてのFuture
オブジェクトの終了後にコールバック関数を実行します。Future
の配列にM
個の要素がある場合、MATLAB クライアントはコールバック関数を 1 回だけ実行します。
parfeval
の計算に対する afterEach
の呼び出し
afterEach
を使用して、parfeval
の各計算結果に対して自動的に関数を呼び出すことができます。
parfeval
を使用して、ワーカーで乱数ベクトルを計算します。parfeval
は parpool
が作成されていなければ、自動的に既定の基本設定で作成します。
for idx = 1:10 f(idx) = parfeval(@rand, 1, 1000, 1); end
これらのベクトルが作成されたら、それぞれの最大要素を表示します。afterEach
は、各 Future が使用可能になると、それぞれの出力に対して関数ハンドルを実行します。
afterEach(f, @(r) disp(max(r)), 0);
0.9975 0.9990 0.9982 0.9991 0.9982 0.9998 0.9999 0.9986 0.9996 0.9990
parfeval
の計算に対する afterAll
の呼び出し
afterAll
を使用して、parfeval
の計算の出力すべての結合に対して自動的に関数を呼び出すことができます。
parfeval
を使用して、ワーカーで乱数ベクトルを計算します。parfeval
は parpool
が作成されていなければ、自動的に既定の基本設定で作成します。
for idx = 1:10 f(idx) = parfeval(@rand, 1, 1000, 1); end
ベクトルの作成後、これらすべての最大要素を表示します。afterAll
は、すべての Future が使用可能になったら、これらの出力の結合に対して関数ハンドルを実行します。
afterAll(f, @(r) fprintf("Maximum element is %1.4f\n",max(r)), 0);
afterEach
と afterAll
の組み合わせ
afterEach
と afterAll
を組み合わせて、Future の結果に対して、さらに関数を自動的に呼び出すことができます。afterEach
と afterAll
はいずれも、afterEach
と afterAll
で再利用可能な future 変数を生成します。
parfeval
を使用して、ワーカーで乱数ベクトルを計算します。parfeval
は parpool
が作成されていなければ、自動的に既定の基本設定で作成します。
for idx= 1:10 f(idx) = parfeval(@rand, 1, 1000, 1); end
ベクトルが使用可能になったら、各ベクトルの最大要素を計算します。afterEach
は、Future が使用可能になったら、各 Future の出力に対して関数ハンドルを実行し、別の Future を作成して結果を格納します。
maxFuture = afterEach(f, @(r) max(r), 1);
これらの最小値を計算するために、この新しい Future について afterAll
を呼び出します。afterAll
は、すべての Future が完了した後、すべての Future の出力引数の結合に対して関数を実行します。この場合、afterAll
は、maxFuture
の完了後にその出力に対して関数 min
を実行し、別の Future を作成して結果を格納します。
minFuture = afterAll(maxFuture, @(r) min(r), 1);
この結果は、fetchOutputs
を使用して取得できます。fetchOutput
は、Future が結果の収集を完了するまで待機します。
fetchOutputs(minFuture)
ans = 0.9970
fetchOutputs
を future 変数で呼び出して、afterEach
の結果を確認できます。
fetchOutputs(maxFuture)
ans = 10×1
0.9984
0.9996
1.0000
0.9999
0.9999
0.9970
0.9999
0.9998
0.9998
0.9997
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);
future 変数のエラーの処理
future 変数の計算でエラーが発生した場合、既定で afterEach
はエラーの発生した要素についてその関数を評価しません。たとえば、更新するユーザー インターフェイスがあるなど、任意のエラーを処理する場合は、名前と値のペア PassFuture
を使用できます。true
に設定されている場合、future 変数はコールバック関数に渡されます。これに対して fetchOutputs
を呼び出し、出力を処理して、考えられるエラーすべてに対処できます。
parfeval
を使用してワーカーに計算を送信します。parfeval
は parpool
が作成されていなければ、自動的に既定の基本設定で作成します。parfeval
の計算でエラーが発生した場合、future 変数はエラーになり、その Error
プロパティに反映されます。
errorFuture = parfeval(@(n) randn(n), 0, 0.5); wait(errorFuture); errorFuture.Error
ans = ParallelException with properties: identifier: 'MATLAB:NonIntegerInput' message: 'Size inputs must be integers.' cause: {} remotecause: {[1×1 MException]} stack: [1×1 struct] Correction: []
その Future に対して afterEach
を使用すると、エラーになった Future の要素についてコールバック関数は評価されません。以下のコードでは、Future のエラーのため、msgbox
が実行されません。
afterEach(errorFuture, @() msgbox('Operation completed'), 0);
結果がエラーになる Future を扱うには、afterEach
を呼び出すときに名前と値のペア PassFuture
を使用します。出力ではなく future 変数がコールバック関数に渡されます。future 変数に対して fetchOutputs
を呼び出し、その出力を処理します。Future でエラーが発生すると、fetchOutputs
によりエラーがスローされます。これをキャッチして処理できます。以下のコードはエラー ダイアログ ボックスを表示します。
afterEach(errorFuture, @handleError, 0, 'PassFuture', true);
function handleError(f) try output = fetchOutputs(f); % Do something with the output catch errordlg('Operation failed'); end end
参考
parfeval
| parfevalOnAll
| Future
| afterEach
| afterAll