查询及撤销 parfeval future
当您使用 parfeval 或 parfevalOnAll 在后台运行计算时,您会创建称为 future 对象。您可以使用 future 的 State 属性来查明它是正在运行、排队还是完成。您还可以使用并行池的 FevalQueue 属性来访问正在运行和排队的 future。要取消 future,可以使用 cancel 函数。在此示例中,您:
使用
cancel直接取消 future。检查已完成 future 的完成错误。
使用
FevalQueue属性来访问 future。
将工作添加到队列
创建一个具有两个工作单元的并行池 p。
p = parpool(2);
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to parallel pool with 2 workers.
当您使用 parfeval 在后台运行计算时,该函数会为每个计算创建一个 future 并将其添加到池队列中。任务将保留在队列中,直到工作单元变为空闲。当一个工作单元空闲时,如果队列不空,它就开始计算任务。当工作单元完成一项任务时,该任务将从队列中移除并且工作单元变为空闲状态。
为了提高效率,预先分配一个 future 对象数组。使用 parfeval 指示工作单元在后台执行函数 pause。对第三个 future 使用 1 参量,对所有其他 future 使用 Inf 参量。
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
每次使用 parfeval 都会返回一个 future 对象,该对象代表着某个函数在工作单元上的执行。除了第三个 future 之外,每个 future 都需要花费无限的时间来计算。parfeval(@pause,0,Inf) 创建的 future 是可以减慢队列速度的 future 的一个极端情况。
直接取消 future
您可以使用 State 属性来获取 future 的状态。构建 f 中每个 future 的元胞数组。
{f.State}ans = 1×5 cell
{'running'} {'running'} {'queued'} {'queued'} {'queued'}
除第三项任务外,所有任务都永远暂停。
直接用 cancel 取消第二个 future。
cancel(f(2));
{f.State}ans = 1×5 cell
{'running'} {'finished'} {'queued'} {'queued'} {'queued'}
取消第二个 future 后,第三个 future 将运行。等到第三个 future 完成,然后再次检查状态。
wait(f(3));
{f.State}ans = 1×5 cell
{'running'} {'finished'} {'finished'} {'running'} {'queued'}
第三个 future 现在的状态是 'finished'。
检查完成错误
当 future 完成时,它的 State 属性变为 'finished'。要区分被取消和正常完成的期货,请使用 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):
正如消息属性所示,代码取消了第二个 future。如 message 属性中所述,第二个未来被取消了。第三个 future 成功完成,因此没有错误消息。
取消池队列中的 future
您可以使用 FevalQueue 属性来访问池队列中的 future。
p.FevalQueue
ans =
FevalQueue with properties:
QueuedFutures: [1x1 parallel.FevalFuture]
RunningFutures: [2x1 parallel.FevalFuture]
该队列有两个属性:RunningFutures 和 QueuedFutures。RunningFutures 属性是与当前正在运行的任务相对应的 future 数组。
disp(p.FevalQueue.RunningFutures)
2x1 FevalFuture array:
ID State FinishDateTime Function Error
--------------------------------------------------------
1 22 running @pause
2 25 running @pause
QueuedFutures 属性是与当前排队且未运行的任务相对应的 future 数组。
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
您可以取消单个 future 或 future 数组。取消 QueuedFutures 中的所有 future。
cancel(p.FevalQueue.QueuedFutures);
{f.State}ans = 1×5 cell
{'running'} {'finished'} {'finished'} {'running'} {'finished'}
RunningFutures 和 QueuedFutures 都是按照从最新到最旧的顺序排序的,不管 f 是否也是按照从最新到最旧的顺序排序的。每个 future 在客户端的整个生命周期内都有一个唯一的 ID 属性。检查 ID 中每个 future 的 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
将结果与每个 ID 的 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
这里,RunningFutures 是一个包含 f(1) 和 f(4) 的数组。如果取消 RunningFutures(2),则取消第四个 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);