主要内容

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

使用 afterEachafterAll 运行回调函数

当您使用 parfevalparfevalOnAllafterEachafterAll 在后台或并行池中运行函数时,您会创建 Future。您可以使用 afterEachafterAll 在一个或多个 Future 对象完成后自动运行回调函数。

  • 如果使用 afterEach 函数,则在每个 Future 对象完成后,MATLAB® 会运行回调函数。如果 Future 数组有 M 个元素,则 MATLAB 客户端运行回调函数 M 次。

  • 如果使用 afterAll 函数,则在所有 Future 对象完成后,MATLAB 会运行回调函数。如果 Future 数组有 M 元素,则 MATLAB 客户端运行回调函数仅运行一次。

afterEach 计算中调用 parfeval

您可以使用 afterEach 自动对 parfeval 计算的每个结果调用函数。

使用 parfeval 计算工作单元中的随机向量。在默认设置下,parfeval 会自动创建一个 parpool,如果尚未存在。

for idx = 1:10
    f(idx) = parfeval(@rand, 1, 1000, 1);
end

显示每个向量创建后的最大元素。当每个 future 准备就绪时,afterEach 会在其输出上执行函数句柄。

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

afterAll 计算中调用 parfeval

您可以使用 afterAll 自动调用 parfeval 计算的所有组合输出的函数。

使用 parfeval 计算工作单元中的随机向量。在默认设置下,parfeval 会自动创建一个 parpool,如果尚未存在。

for idx = 1:10
    f(idx) = parfeval(@rand, 1, 1000, 1);
end

显示创建所有这些向量后它们中的最大元素。当所有 future 都准备就绪时,afterAll 会对所有 future 的组合输出执行函数句柄。

afterAll(f, @(r) fprintf("Maximum element is %1.4f\n",max(r)), 0);

组合使用 afterEach afterAll

您可以将 afterEachafterAll 组合使用,以自动对未来对象的结果调用更多函数。afterEachafterAll 都生成可以在 afterEachafterAll 中再次使用的 future 变量。

使用 parfeval 计算工作单元中的随机向量。在默认设置下,parfeval 会自动创建一个 parpool,如果尚未存在。

for idx= 1:10
    f(idx) = parfeval(@rand, 1, 1000, 1);
end

当每个向量准备就绪时,计算其中的最大元素。当每个 future 准备就绪时,afterEach 会在其输出上执行函数句柄,并创建另一个 future 来保存结果。

maxFuture = afterEach(f, @(r) max(r), 1);

为了计算它们中的最小值,在这个新的 future 上调用 afterAllafterAll 在所有 future 完成后,对所有 future 的组合输出参量执行一个函数。在此情况下,afterAll 在完成执行后,对 maxFuture 的输出执行函数 min,并创建另一个未来对象来存储结果。

minFuture = afterAll(maxFuture, @(r) min(r), 1);

您可以使用 fetchOutputs 获取结果。fetchOutput 等到 future 完成后再收集结果。

fetchOutputs(minFuture)
ans = 0.9970

您可以通过在其 future 变量上调用 afterEach 来检查 fetchOutputs 的结果。

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

使用 afterEachafterAll 异步更新用户界面

此示例显示如何在计算完成时更新用户界面。当您使用 parfeval 将计算卸载给工作单元时,工作单元执行计算时所有用户界面都会做出响应。您可以使用 waitbar 来创建一个简单的用户界面。

  • 每次计算完成后使用 afterEach 更新用户界面。

  • 所有计算完成后使用 afterAll 更新用户界面。

使用 waitbar 创建图形句柄,h。当您使用 afterEachafterAll 时,waitbar 函数会更新图形句柄。有关句柄对象的更多信息,请参阅 句柄对象行为

h = waitbar(0,'Waiting...');

使用 parfeval 计算随机矩阵特征值的实部。在默认设置下,如果尚未创建并行池,parfeval 会自动创建一个并行池。为了提高效率,预先分配一个 Future 对象数组。

f(1:100) = parallel.FevalFuture;
for idx = 1:100
    f(idx) = parfeval(@(n) real(eig(randn(n))),1,5e2); 
end

您可以使用 afterEach 自动对 parfeval 计算的每个结果调用函数。使用 afterEach 来安排另一组 future 对象,以在 f 中的每个 future 完成后计算每个输出数组中的最大值。

maxFuture = afterEach(f,@max,1);

您可以使用 State 属性来获取 future 的状态。定义一个匿名函数,将 h 的分数等待条长度更新为已完成执行的 Future 对象的比例。如果 updateWaitbar 中对应 true 对象的 State 属性为 Future,则 f 匿名函数计算元素为 "finished" 的逻辑数组的平均值。

updateWaitbar = @(~) waitbar(mean({f.State} == "finished"),h);

使用 afterEachupdateWaitbarmaxFuture 中的每个 future 完成后更新分数等待条长度。所有计算完成后,使用 afterAlldelete 关闭等待栏。

updateWaitbarFutures = afterEach(f,updateWaitbar,0);
afterAll(updateWaitbarFutures,@(~) delete(h),0)

使用 afterAllhistogram 来显示所有 future 完成后 maxFuture 中结果的直方图。

showsHistogramFuture = afterAll(maxFuture,@histogram,0);

处理 future 变量中的错误

当 future 变量的计算导致错误时,默认情况下,afterEach 不会对失败的元素评估其函数。如果您想处理任何错误,例如,您有一个想要更新的用户界面,您可以使用名称-值对 PassFuture。当设置为 true 时,future 变量将传递给回调函数。您可以对其调用 fetchOutputs,处理输出并处理任何可能的错误。

使用 parfeval 将计算结果发送给工作单元。在默认设置下,parfeval 会自动创建一个 parpool,如果尚未存在。如果您的 parfeval 计算导致错误,则 future 变量会出现错误,并且其 Error 属性会反映该错误。

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: []

如果对 future 使用 afterEach,则回调函数不会对 future 出现错误的元素进行评估。在下面的代码中,由于 future 错误,msgbox 未被执行。

afterEach(errorFuture, @() msgbox('Operation completed'), 0);

为了处理导致错误的 future,请在调用 PassFuture 时使用名称-值对 afterEach。Future 变量被传递给回调函数而不是其输出。在 future 变量上调用 fetchOutputs,并处理其输出。如果 future 导致错误,fetchOutputs 会抛出一个您可以捕获和处理的错误。以下代码显示错误对话框。

afterEach(errorFuture, @handleError, 0, 'PassFuture', true);

function handleError(f)
    try
        output = fetchOutputs(f);
        % Do something with the output
    catch
        errordlg('Operation failed');
    end
end

另请参阅

| | | |