Use afterEach
and afterAll
to Run Callback
Functions
You create a Future
when you run
functions in the background or on a parallel pool using parfeval
, parfevalOnAll
, afterEach
, or
afterAll
. You can
use afterEach
and afterAll
to automatically run a
callback function after one or more Future
objects finish.
If you use
afterEach
, MATLAB® runs the callback function after eachFuture
object finishes. If theFuture
array hasM
elements, the MATLAB client runs the callback functionM
times.If you use
afterAll
, MATLAB runs the callback function after allFuture
objects finish. If theFuture
array hasM
elements, the MATLAB client runs the callback function only runs once.
Call afterEach
on parfeval
Computations
You can use afterEach
to automatically invoke functions on each of the results of parfeval
computations.
Use parfeval
to compute random vectors in the workers. With default preferences, parfeval
creates a parpool
automatically if there is not one already created.
for idx = 1:10 f(idx) = parfeval(@rand, 1, 1000, 1); end
Display the maximum element in each of those vectors after they are created. afterEach
executes the function handle on the output of each future when they become ready.
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
Call afterAll
on parfeval
Computations
You can use afterAll
to automatically invoke functions on all of the combined outputs of your parfeval
computations.
Use parfeval
to compute random vectors in the workers. With default preferences, parfeval
creates a parpool
automatically if there is not one already created.
for idx = 1:10 f(idx) = parfeval(@rand, 1, 1000, 1); end
Display the maximum element among all of those vectors after they are created. afterAll
executes the function handle on the combined output of all the futures when they all become ready.
afterAll(f, @(r) fprintf("Maximum element is %1.4f\n",max(r)), 0);
Combine afterEach
and afterAll
You can combine afterEach
and afterAll
to automatically invoke more functions on the results of futures. Both afterEach
and afterAll
generate future variables that can be used again in afterEach
and afterAll
.
Use parfeval
to compute random vectors in the workers. With default preferences, parfeval
creates a parpool
automatically if there is not one already created.
for idx= 1:10 f(idx) = parfeval(@rand, 1, 1000, 1); end
Compute the largest element in each of those vectors when they become ready. afterEach
executes the function handle on the output of each future when they become ready and creates another future to hold the results.
maxFuture = afterEach(f, @(r) max(r), 1);
To compute the minimum value among them, call afterAll
on this new future. afterAll
executes a function on the combined output arguments of all the futures after they all complete. In this case, afterAll
executes the function min
on the outputs of maxFuture
after completing and creates another future to hold the result.
minFuture = afterAll(maxFuture, @(r) min(r), 1);
You can fetch the result using fetchOutputs
. fetchOutput
waits until the future completes to gather the results.
fetchOutputs(minFuture)
ans = 0.9970
You can check the result of afterEach
by calling fetchOutputs
on its future variable.
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
Update User Interface Asynchronously Using afterEach
and afterAll
This example shows how to update a user interface as computations complete. When you offload computations to workers using parfeval
, all user interfaces are responsive while workers perform the computations. You can use waitbar
to create a simple user interface.
Use
afterEach
to update the user interface after each computation completes.Use
afterAll
to update the user interface after all the computations complete.
Use waitbar
to create a figure handle, h
. When you use afterEach
or afterAll
, the waitbar
function updates the figure handle. For more information about handle objects, see Handle Object Behavior.
h = waitbar(0,'Waiting...');
Use parfeval
to calculate the real part of the eigenvalues of random matrices. With default preferences, parfeval
creates a parallel pool automatically if one has not already been created. For efficiency, preallocate an array of Future
objects.
f(1:100) = parallel.FevalFuture; for idx = 1:100 f(idx) = parfeval(@(n) real(eig(randn(n))),1,5e2); end
You can use afterEach
to automatically invoke functions on each of the results of the parfeval
computations. Use afterEach
to schedule another set of future objects to compute the largest value in each of the output arrays after each future in the f
completes.
maxFuture = afterEach(f,@max,1);
You can use the State
property to obtain the status of futures. Define an anonymous function that updates the fractional wait bar length of h
to the fraction of Future
objects that have finished executing. The updateWaitbar
anonymous function computes the mean of a logical array in which an element is true
if the State
property of the corresponding Future
object in f
is "finished"
.
updateWaitbar = @(~) waitbar(mean({f.State} == "finished"),h);
Use afterEach
and updateWaitbar
to update the fractional wait bar length after each future in maxFuture
completes. Use afterAll
and delete
to close the wait bar after all the computations are complete.
updateWaitbarFutures = afterEach(f,updateWaitbar,0); afterAll(updateWaitbarFutures,@(~) delete(h),0)
Use afterAll
and histogram
to show a histogram of the results in maxFuture
after all the futures complete.
showsHistogramFuture = afterAll(maxFuture,@histogram,0);
Handle Errors in Future Variables
When computations for future variables result in an error, by default, afterEach
does not evaluate its function on the elements that failed. If you want to handle any errors, for example, you have a user interface that you want to update, you can use the name-value pair PassFuture
. When set to true
, the future variable is passed to the callback function. You can call fetchOutputs
on it, process the outputs, and handle any possible errors.
Send computations to the workers using parfeval
. With default preferences, parfeval
creates a parpool
automatically if there is not one already created. If your parfeval
computations result in an error, the future variable errors, and its Error
property reflects it.
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: []
If you use afterEach
on that future, the callback function is not evaluated on those elements in the future that errored. In the code below, the msgbox
is not executed because the future errors.
afterEach(errorFuture, @() msgbox('Operation completed'), 0);
To handle futures that result in errors, use the name-value pair PassFuture
when calling afterEach
. The future variable is passed to the callback function instead of its outputs. Call fetchOutputs
on the future variable, and process its outputs. If the future results in an error, fetchOutputs
throws an error that you can catch and handle. The following code shows an error dialog box.
afterEach(errorFuture, @handleError, 0, 'PassFuture', true);
function handleError(f) try output = fetchOutputs(f); % Do something with the output catch errordlg('Operation failed'); end end
See Also
parfeval
| parfevalOnAll
| Future
| afterEach
| afterAll