使用 afterEach 和 afterAll 运行回调函数
当您使用 parfeval、parfevalOnAll、afterEach 或 afterAll 在后台或并行池中运行函数时,您会创建 Future。您可以使用 afterEach 和 afterAll 在一个或多个 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
您可以将 afterEach 和 afterAll 组合使用,以自动对未来对象的结果调用更多函数。afterEach 和 afterAll 都生成可以在 afterEach 和 afterAll 中再次使用的 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 上调用 afterAll。afterAll 在所有 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
使用 afterEach 和 afterAll 异步更新用户界面
此示例显示如何在计算完成时更新用户界面。当您使用 parfeval 将计算卸载给工作单元时,工作单元执行计算时所有用户界面都会做出响应。您可以使用 waitbar 来创建一个简单的用户界面。
每次计算完成后使用
afterEach更新用户界面。所有计算完成后使用
afterAll更新用户界面。
使用 waitbar 创建图形句柄,h。当您使用 afterEach 或 afterAll 时,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);使用 afterEach 和 updateWaitbar 在 maxFuture 中的每个 future 完成后更新分数等待条长度。所有计算完成后,使用 afterAll 和 delete 关闭等待栏。
updateWaitbarFutures = afterEach(f,updateWaitbar,0); afterAll(updateWaitbarFutures,@(~) delete(h),0)
使用 afterAll 和 histogram 来显示所有 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
另请参阅
parfeval | parfevalOnAll | Future | afterEach | afterAll