Main Content

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

使用 afterEachafterAll 运行回调函数

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

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

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

parfeval 计算中调用 afterEach

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

使用 parfeval 计算工作进程中的随机向量。使用默认首选项时,如果尚未创建 parpoolparfeval 会自动创建一个。

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

显示每个向量创建后的最大元素。当每个未来准备就绪时,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

parfeval 计算中调用 afterAll

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

使用 parfeval 计算工作进程中的随机向量。使用默认首选项时,如果尚未创建 parpoolparfeval 会自动创建一个。

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

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

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

合并 afterEach afterAll

您可以结合 afterEach afterAll 来在未来的结果上自动调用更多函数。afterEachafterAll 都生成可以在 afterEachafterAll 中再次使用的未来变量。

使用 parfeval 计算工作进程中的随机向量。使用默认首选项时,如果尚未创建 parpoolparfeval 会自动创建一个。

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

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

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

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

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

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

fetchOutputs(minFuture)
ans = 0.9970

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

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 来安排另一组未来对象,以在 f 中的每个未来完成后计算每个输出数组中的最大值。

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

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

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

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

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

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

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

处理未来变量中的错误

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

使用 parfeval 将计算结果发送给工作进程。使用默认首选项时,如果尚未创建 parpoolparfeval 会自动创建一个。如果您的 parfeval 计算导致错误,则未来变量会出现错误,并且其 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: []

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

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

为了处理导致错误的未来,请在调用 afterEach 时使用名称-值对 PassFuture。未来变量被传递给回调函数而不是其输出。在未来变量上调用 fetchOutputs,并进程其输出。如果未来导致错误,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

另请参阅

| | | |