主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

查询及撤销 parfeval future

当您使用 parfevalparfevalOnAll 在后台运行计算时,您会创建称为 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]

该队列有两个属性:RunningFuturesQueuedFuturesRunningFutures 属性是与当前正在运行的任务相对应的 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'}

RunningFuturesQueuedFutures 都是按照从最新到最旧的顺序排序的,不管 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

将结果与每个 IDRunningFutures 属性进行比较。

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

您可以使用 RunningFuturesQueuedFutures 来访问尚未完成的 future。使用 RunningFutures 取消 f(4)

rf2 = p.FevalQueue.RunningFutures(2);
cancel(rf2)
rf2.State
ans = 
'finished'

要取消队列中所有的 future,请使用此代码。

cancel(p.FevalQueue.QueuedFutures);
cancel(p.FevalQueue.RunningFutures);