Query and Cancel parfeval
Futures
When you use parfeval
or parfevalOnAll
to run computations in the background, you create objects called futures. You can use the State
property of a future to find out whether it is running, queued or finished. You can also use the FevalQueue
property of a parallel pool to access running and queued futures. To cancel futures, you can use the cancel
function. In this example, you:
Use
cancel
to cancel futures directly.Check completion errors on completed futures.
Use the
FevalQueue
property to access futures.
Add Work to Queue
Create a parallel pool p
with two workers.
p = parpool(2);
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to parallel pool with 2 workers.
When you use parfeval
to run computations in the background, the function creates and adds a future for each computation to the pool queue. Tasks remain in the queue until a worker becomes idle. When a worker becomes idle, it starts to compute a task if the queue is not empty. When a worker completes a task, the task is removed from the queue and the worker becomes idle.
For efficiency, preallocate an array of future objects. Use parfeval
to instruct the workers to execute the function pause
in the background. Use an argument of 1
for the third future, and an argument of Inf
for all other futures.
f(1:5) = parallel.FevalFuture; for n = 1:5 if n == 3 f(n) = parfeval(@pause,0,1); else f(n) = parfeval(@pause,0,Inf); end end
Each use of parfeval
returns a future object that represents the execution of a function on a worker. Except for the third future, every future will take an infinite amount of time to compute. The future created by parfeval(@pause,0,Inf)
is an extreme case of a future which can slow down a queue.
Cancel Futures Directly
You can use the State
property to obtain the status of futures. Construct a cell array of the state of each future in f
.
{f.State}
ans = 1×5 cell
{'running'} {'running'} {'queued'} {'queued'} {'queued'}
Every task except for the third pauses forever.
Cancel the second future directly with cancel
.
cancel(f(2)); {f.State}
ans = 1×5 cell
{'running'} {'finished'} {'queued'} {'queued'} {'queued'}
After you cancel the second future, the third future runs. Wait until the third future completes, then examine the states again.
wait(f(3)); {f.State}
ans = 1×5 cell
{'running'} {'finished'} {'finished'} {'running'} {'queued'}
The third future now has the state 'finished'
.
Check Completion Errors
When a future completes, its State
property becomes 'finished'
. To distinguish between futures which are cancelled and complete normally, use the Error
property.
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):
The code cancels the second future, as the message property indicates. The second future was cancelled, as stated in the message
property. The third future completes without error, and therefore does not have an error message.
Cancel Futures in Pool Queue
You can use the FevalQueue
property to access the futures in the pool queue.
p.FevalQueue
ans = FevalQueue with properties: QueuedFutures: [1x1 parallel.FevalFuture] RunningFutures: [2x1 parallel.FevalFuture]
The queue has two properties: RunningFutures
and QueuedFutures
. The RunningFutures
property is an array of futures corresponding to tasks that are currently running.
disp(p.FevalQueue.RunningFutures)
2x1 FevalFuture array: ID State FinishDateTime Function Error -------------------------------------------------------- 1 22 running @pause 2 25 running @pause
The QueuedFutures
property is an array of futures corresponding to tasks that are currently queued and not running.
disp(p.FevalQueue.QueuedFutures)
FevalFuture with properties: ID: 26 Function: @pause CreateDateTime: 24-Oct-2023 17:28:51 StartDateTime: RunningDuration: 0 days 0h 0m 0s State: queued Error: none
You can cancel a single future or an array of futures. Cancel all the futures in QueuedFutures
.
cancel(p.FevalQueue.QueuedFutures); {f.State}
ans = 1×5 cell
{'running'} {'finished'} {'finished'} {'running'} {'finished'}
RunningFutures
and QueuedFutures
are sorted from newest to oldest, regardless of whether f
is in order from newest to oldest. Each future has a unique ID
property for the lifetime of the client. Check the ID
property of each of the futures in f
.
disp(f)
1x5 FevalFuture array: ID State FinishDateTime Function Error -------------------------------------------------------------- 1 22 running @pause 2 23 finished (unread) 24-Oct-2023 17:29:16 @pause Error 3 24 finished (unread) 24-Oct-2023 17:29:17 @pause 4 25 running @pause 5 26 finished (unread) 24-Oct-2023 17:29:52 @pause Error
Compare the result against the ID
property of each of the RunningFutures
.
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 = 22 p.FevalQueue.RunningFutures(2): ID = 25
Here, RunningFutures
is an array containing f(1)
and f(4)
. If you cancel RunningFutures(2)
, you cancel the fourth future f(4)
.
Sometimes, futures are not available in the workspace, for example, if you execute the same piece of code twice before it finishes, or if you use parfeval
in a function. You can cancel futures that are not available in the workspace.
Clear f
from the workspace.
clear f
You can use RunningFutures
and QueuedFutures
to access futures that have not yet completed. Use RunningFutures
to cancel f(4)
.
rf2 = p.FevalQueue.RunningFutures(2); cancel(rf2) rf2.State
ans = 'finished'
To cancel all the futures still in the queue, use this code.
cancel(p.FevalQueue.QueuedFutures); cancel(p.FevalQueue.RunningFutures);