使用 afterEach
和 afterAll
运行回调函数
当您使用 parfeval
、parfevalOnAll
、afterEach
或 afterAll
在后台或并行池中运行函数时,您会创建 Future
。您可以使用 afterEach
和 afterAll
在一个或多个 Future
对象完成后自动运行回调函数。
如果使用
afterEach
,MATLAB® 将在每个Future
对象完成后运行回调函数。如果Future
数组有M
个元素,则 MATLAB 客户端运行回调函数M
次。如果使用
afterAll
,MATLAB 会在所有Future
对象完成后运行回调函数。如果Future
数组有M
元素,则 MATLAB 客户端运行回调函数仅运行一次。
在 parfeval
计算中调用 afterEach
您可以使用 afterEach
自动对 parfeval
计算的每个结果调用函数。
使用 parfeval
计算工作进程中的随机向量。使用默认首选项时,如果尚未创建 parpool
,parfeval
会自动创建一个。
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
计算工作进程中的随机向量。使用默认首选项时,如果尚未创建 parpool
,parfeval
会自动创建一个。
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
来在未来的结果上自动调用更多函数。afterEach
和 afterAll
都生成可以在 afterEach
和 afterAll
中再次使用的未来变量。
使用 parfeval
计算工作进程中的随机向量。使用默认首选项时,如果尚未创建 parpool
,parfeval
会自动创建一个。
for idx= 1:10 f(idx) = parfeval(@rand, 1, 1000, 1); end
当每个向量准备就绪时,计算其中的最大元素。当每个未来准备就绪时,afterEach
会在其输出上执行函数句柄,并创建另一个未来来保存结果。
maxFuture = afterEach(f, @(r) max(r), 1);
为了计算它们中的最小值,在这个新的未来上调用 afterAll
。afterAll
在所有未来完成后,对所有未来的组合输出参量执行一个函数。在这种情况下,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
使用 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
来安排另一组未来对象,以在 f
中的每个未来完成后计算每个输出数组中的最大值。
maxFuture = afterEach(f,@max,1);
您可以使用 State
属性来获取期货的状态。定义一个匿名函数,将 h
的分数等待条长度更新为已完成执行的 Future
对象的比例。如果 f
中对应 Future
对象的 State
属性为 "finished"
,则 updateWaitbar
匿名函数计算元素为 true
的逻辑数组的平均值。
updateWaitbar = @(~) waitbar(mean({f.State} == "finished"),h);
使用 afterEach
和 updateWaitbar
在 maxFuture
中的每个未来完成后更新分数等待条长度。所有计算完成后,使用 afterAll
和 delete
关闭等待栏。
updateWaitbarFutures = afterEach(f,updateWaitbar,0); afterAll(updateWaitbarFutures,@(~) delete(h),0)
使用 afterAll
和 histogram
来显示所有期货完成后 maxFuture
中结果的直方图。
showsHistogramFuture = afterAll(maxFuture,@histogram,0);
处理未来变量中的错误
当未来变量的计算导致错误时,默认情况下,afterEach
不会对失败的元素评估其函数。如果您想处理任何错误,例如,您有一个想要更新的用户界面,您可以使用名称-值对 PassFuture
。当设置为 true
时,未来变量将传递给回调函数。您可以对其调用 fetchOutputs
,进程输出并处理任何可能的错误。
使用 parfeval
将计算结果发送给工作进程。使用默认首选项时,如果尚未创建 parpool
,parfeval
会自动创建一个。如果您的 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
另请参阅
parfeval
| parfevalOnAll
| Future
| afterEach
| afterAll