Background and Asynchronous Execution
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
Written against MATLAB R2026b. None of the background or timer examples is run: GNU Octave 11.3.0 has no parfeval, backgroundPool, timer, fetchOutputs or afterEach (a check with exist returned 0 for each, run in Octave 11.3.0), so every listing is labelled "not run here" and was checked line by line against the R2026b documentation. Output that appears below is the documentation’s own, and where a message text cannot be verified the page says that it varies. The backgroundPool function and parfeval with it were introduced in R2021b; cancelAll is from R2022a.
By default MATLAB runs one statement at a time in the foreground, and the Command Window is busy until it finishes. Two mechanisms in base MATLAB let a session do something else in the meantime. A background pool runs a function on a separate worker thread and hands you a Future object immediately, so you can keep working and collect the result later. A timer object schedules a callback to run at a specified time or repeatedly, inside the same session. Parallel loops, parallel pools and GPUs belong to the Parallel Computing Toolbox, which is covered only by a pointer to Toolboxes and Add-On Products. Before choosing either mechanism, measure first: see Profiling and Timing.
Synchronous and asynchronous code
The documentation contrasts the two models.
| Synchronous (ordinary code) | Asynchronous (parfeval, afterEach) |
|---|---|
MATLAB waits for the function to complete. |
MATLAB does not wait; it returns a |
MATLAB runs the code immediately. |
MATLAB runs the code when a worker is available. |
Outputs are in the current workspace. |
You copy the outputs to the workspace with |
Any function or object can be used. |
Most functions and objects can be used; on the background pool, a function must have thread support. |
The current workspace is available to the function. |
Most variables of the workspace are available, copied into the call. |
backgroundPool and parfeval
F = parfeval(backgroundPool,fcn,numFcnOut,X1,...,Xm) schedules the function handle fcn to run on the background pool with the inputs X1,...,Xm and numFcnOut outputs. backgroundPool itself returns the pool object, whose read-only properties are NumWorkers (1 without Parallel Computing Toolbox, otherwise the number of physical cores), Busy (true while work is outstanding) and FevalQueue (the pending and running futures). The function runs on a background worker, not in your session, so it cannot change your workspace and gets copies of its inputs.
f = parfeval(backgroundPool,@magic,1,3); % schedule magic(3), one output
% ... other MATLAB code runs here at the same time ...
A = fetchOutputs(f) % waits until magic has finished
(Not run here.) The documentation shows the displayed result as the 3-by-3 matrix 8 1 6; 3 5 7; 4 9 2, the output of magic(3). fetchOutputs waits for the function to finish before it returns, so you rarely need an explicit wait.
The syntax parfeval(fcn,numFcnOut,X1,...) without the pool is meant for code written for Parallel Computing Toolbox: with no license the function runs in serial, with one it uses the parallel resources (see below). Pass backgroundPool explicitly when you want the background pool.
Which functions can run in the background
The background pool is a thread-based environment, so the function and everything it calls must support threads. Hundreds of MATLAB functions do; the function reference page of each says so in its Extended Capabilities section ("Thread-Based Environment"), and the documentation maintains a filtered list. In general, the documentation says that functionality in Graphics, App Building, External Language Interfaces, Files and Folders, and Environment and Settings is not supported. Three consequences follow:
-
A function that draws, builds a user interface or runs a file-system command should be run in the foreground; compute in the background and plot the result afterwards.
-
Persistent data and the random number generator state are shared between
backgroundPooland a thread pool (parpool("threads")) because they use the same resources, and activity on one can block the other. -
When code already runs on a thread-based worker, a call to
backgroundPoolreturns an empty pool object and the code is evaluated serially.
Future objects
A Future represents a function that you scheduled. Its read-only properties are the status board of the job:
| Property | Meaning |
|---|---|
|
|
|
An |
|
The outputs, as a cell array. Empty while the job runs or when it finished with an error. |
|
What was scheduled, and how many outputs it returns (the function must return at least that many). |
|
When it was created, started and finished, and how long it has been running. |
|
The text the function would display in the Command Window ( |
|
An identifier, and whether |
Futures come in four kinds: FevalFuture from parfeval, FevalOnAllFuture from parfevalOnAll, and AfterEachFuture and AfterAllFuture from the callbacks below. The documentation states that a future made by afterEach or afterAll runs its function in your current session, not in the background.
The life of a future on the background pool is a small state machine. A cancelled future also ends in 'finished', with a cancellation recorded in Error.
Collecting results
-
fetchOutputs(F)returns the outputs of a future or of an array of futures, waiting for each to finish. For an array, the *j*th output of every element is concatenated along the first dimension; if that is not possible usefetchOutputs(F,UniformOutput=false), which returns cell arrays. If a function failed,fetchOutputscannot return its result: inspectF.Errorfirst (the message text depends on the function that failed, so it is not quoted here). -
wait(F)blocks until the futures finish;wait(F,state)waits for a givenState, andtf = wait(F,state,timeout)waits at mosttimeoutseconds and returns whether they finished. It is only needed to wait without fetching. -
fetchNext(F)returns the next unread output as soon as any future in an array finishes, which lets you process results in completion order instead of submission order.
The documentation’s pattern for many jobs preallocates an array of futures (F(1:N) = parallel.Future;), fills it in a loop of parfeval calls, and then either calls fetchOutputs(F) for all of them or fetchNext as they arrive:
N = 100;
F(1:N) = parallel.Future; % preallocate the futures
for idx = 1:N
F(idx) = parfeval(backgroundPool,@rank,1,magic(idx));
end
out = fetchOutputs(F); % rank of magic(1) ... magic(100)
disp("Background computations complete.")
(Not run here.) The documentation prints Background computations complete. after the fetch. Preallocating the array is the same habit as for numeric arrays; see Vectorization and Preallocation.
Source: MATLAB documentation: Future, fetchOutputs, wait
Callbacks with afterEach and afterAll
Instead of polling, schedule a function to run when futures finish:
-
B = afterEach(A,fcn,n)runsfcnonce for each element of the future arrayA, with that element’s outputs as inputs, and returns a futureBthat finishes after the last run.nis the number of outputs of the callback;0returns none. -
B = afterAll(A,fcn,n)runsfcnonce, after all the elements ofAhave finished.
By default, afterEach does not run fcn for an element that failed. To handle errors, pass PassFuture=true: the callback then receives the Future itself, so it can call fetchOutputs in a try/catch or read Error. This is how a user interface is kept informed when a background job fails.
for i = 1:10
f(i) = parfeval(backgroundPool,@rand,1,1);
end
afterEach(f,@disp,0); % display each value as it arrives
(Not run here.) The values printed are random and differ from run to run. The callbacks run in your session, in the foreground, when MATLAB is free to run them, so a long callback delays the rest of your work.
Source: MATLAB documentation: afterEach, afterAll
Cancelling
cancel(F) stops every queued or running element of F: it sets State to 'finished' and records the cancellation in Error. The documentation example schedules pause(Inf), shows f.State as 'running', then calls cancel(f) and shows 'finished'. cancelAll (R2022a) stops everything queued on the pool. The documentation warns that some operations, such as save, cannot be interrupted with Ctrl+C and so cannot be stopped by cancel either; and that delete on the background pool is not recommended and cancelAll should be used instead. A long job also blocks the pool: with one worker, later futures stay 'queued' until it ends, so cancel jobs you no longer need.
f = parfeval(backgroundPool,@pause,0,Inf); % a job that never ends
f.State % 'running'
cancel(f)
f.State % 'finished'
(Not run here; the two states are those shown in the documentation example.)
Source: MATLAB documentation: cancel, cancelAll
A heatflow example
The steady state of the plate is a large sparse solve (see Sparse Matrices and Graphs). The function below builds the five-point system and solves it, using only base MATLAB; it is a self-contained stand-in for heatflow.assembleSystem. Sparse linear solves are among the functions with thread support, but check the reference page of each function you use before depending on it.
function T = solvePlate(n)
%SOLVEPLATE Steady temperature on an n-by-n plate, left edge held hot.
e = ones(n,1);
D = spdiags([-e 2*e -e],-1:1,n,n);
A = kron(speye(n),D) + kron(D,speye(n)); % five-point operator
b = zeros(n*n,1);
b(1:n) = 100; % first grid line at 100
T = reshape(A\b,n,n); % solve, then lay out as a grid
end
The function itself (not the background call) was run in Octave 11.3.0 with n = 20: the result is a 20-by-20 full matrix whose values lie between 0 and 100: disp(size(T)) printed 20 20, the range test [all(T(:) >= 0), all(T(:) <= 100)] printed 1 1, and the smallest and largest values were 0.2488 and 90.3784. The background call is not run here. To compute two plate sizes in the background while the session stays free:
f200 = parfeval(backgroundPool,@solvePlate,1,200);
f400 = parfeval(backgroundPool,@solvePlate,1,400);
% ... carry on in the foreground ...
T200 = fetchOutputs(f200);
T400 = fetchOutputs(f400);
With one background worker (no Parallel Computing Toolbox) the two jobs run one after the other, so the gain is a free Command Window, not a shorter total time. With Parallel Computing Toolbox, NumWorkers grows with the physical cores and both can run at once. Anything that touches a figure stays in the foreground: use afterEach, or fetch, and plot yourself.
Timers
A timer object schedules the execution of MATLAB commands inside your session. It does not run in parallel: timers work in the single-threaded MATLAB execution environment, so the actual time can lag the requested time depending on what MATLAB is doing, and drawnow can be called to flush the queue of waiting callbacks.
The procedure is: create the object, set its properties, start it, and delete it when done.
t = timer("TimerFcn",@(~,~) disp("tick"),"Period",1, ...
"ExecutionMode","fixedRate","TasksToExecute",5);
start(t)
wait(t) % block this prompt until the timer stops
delete(t) % always delete a timer object after using it
(Not run here: the name-value syntax follows the timer reference page, which documents t = timer(Name,Value) with property names such as "TasksToExecute". The printed output would be five lines of tick, one per second.)
The properties that matter:
| Property | Role |
|---|---|
|
The callback executed when the timer fires. It must be set before |
|
Callbacks for start, stop (also after an error, to clean up) and error. On an error, |
|
Seconds before the first execution, and between executions. |
|
|
|
How many times the timer fires before it stops. |
|
What happens when a |
|
Any data you want to keep with the timer. |
start(t) starts the timer, startat starts it at a specified time, stop(t) stops it, wait(t) blocks until it stops, timerfind and timerfindall find timer objects, and delete(t) removes the object. Leaving timers running is a common source of surprises: a timer that was never deleted keeps firing after the script that created it has ended. In the documentation’s example a timer with a 1 second period and a callback that needs 1.6 seconds, in drop mode, executes the callback about every 1.6 seconds, because the attempts that arrive while it is still running are dropped. Callback execution may also be delayed if the callback does CPU-intensive work such as updating a figure.
Source: MATLAB documentation: timer, Schedule Command Execution Using Timer, Timer Callback Functions, Handling Timer Queuing Conflicts
Choosing between them
| Need | Use | Why |
|---|---|---|
Run a long computation without freezing the prompt |
|
It runs on another thread. |
Do something every few seconds in the session (poll a log, refresh a display) |
|
It runs in the session; the callback should be short. |
React when a background job finishes |
|
The callback runs in the session when the future completes. |
Run loop iterations or functions on many cores |
|
See the next section. |
What Parallel Computing Toolbox adds
With Parallel Computing Toolbox, backgroundPool automatically scales to use the physical cores (NumWorkers), and parfeval without backgroundPool runs on a parallel pool if one is open (or automatic pool creation is on), including process-backed pools (ProcessPool and cluster pools) on which all functions and objects are supported, not only those with thread support. The toolbox also provides parpool and parfor loops, parfevalOnAll, data queues for sending progress back from workers, and GPU arrays; it is mentioned here only to show where base MATLAB ends. parfor is not used in this section; a parfor loop without the toolbox runs as an ordinary for loop in serial (the documentation says parallel code can run in serial if you do not have the toolbox). See Toolboxes and Add-On Products and Control Flow for for loops.
Pitfalls
-
Forgetting that outputs are not in the workspace. A background function returns a
Future; callfetchOutputs. -
Functions without thread support. Graphics, apps, files and external-language calls cannot run on
backgroundPool. The error for an unsupported function depends on the function; check its Extended Capabilities section. -
Ignoring
Error. A failed future shows up only when you look atF.Erroror fetch it; usePassFuture=trueinafterEachto react. -
Blocking the pool. One endless job holds the queue; cancel it with
cancelorcancelAll, not with the Live Editor Stop button. -
Shared state. Persistent data and random number streams are shared with thread pools; do not assume a background job starts from a fresh random state. See Random Numbers and Reproducibility.
-
Timers that outlive their script. Always
deletethem (aStopFcnthat deletes the timer is the documented clean-up place). -
String callbacks. Use function handles for
TimerFcn; a character vector is evaluated in the base workspace. -
Expecting a timer to be precise. The timer runs in the main thread; a busy session delays it.
-
Long callbacks.
afterEachand timer callbacks run in your session and block it while they run.
Where older books differ
The Davis book (R2010a) has no backgroundPool, parfeval, Future or afterEach: background execution arrived in R2021b, and before that asynchronous work needed Parallel Computing Toolbox or timers. Timer objects are old, and the book-era habit of giving TimerFcn a command as a character vector is now documented as not recommended; use a function handle. Parallel loops (parfor) and the toolbox are outside base MATLAB.