主要内容

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

监控并停止在工作单元上运行的优化任务

本示例演示了如何在并行工作单元上运行优化任务,并从客户端提前终止该任务,同时不丢失中间结果。它在使用 parfeval 进行并行优化时的监控中展示的工作流基础上,引入了客户端控制。

您可以使用 PollableDataQueue 对象将指令从客户端发送给工作单元。如果您的优化函数支持 OutputFcn 选项,您可以定义一个自定义输出函数,该函数在每次迭代时向客户端发送进度数据,并检查客户端发来的指令。此设置允许您在保留截至该时刻收集的所有优化数据的同时,提前终止求解器。

在此示例中,您将运行一次优化,并通过使用 PollableDataQueue 对象从客户端发送终止信号来提前终止该优化。

在本地计算机上启动一个包含一个工作单元的并行池。

parpool("Processes",1);
Starting parallel pool (parpool) using the 'Processes' profile ...
Connected to parallel pool with 1 workers.

定义问题

该问题的目标是将二变量罗森布罗克函数 [1] f(x)=100(x2-x12)2+(1-x1)2 最小化。

定义目标函数,并将初始点设为 [−1.9,2]。

fun = @(x)(100*(x(2) - x(1)^2)^2 + (1 - x(1))^2);
x0 = [-1.9, 2];

设置可轮询数据队列

要向工作单元发送指令,请创建一个 PollableDataQueue 对象,并将 Destination 参量设置为 "any"。此类 PollableDataQueue 对象允许任何工作单元或客户端发送和接收消息。

stopPdq = parallel.pool.PollableDataQueue(Destination="any");

准备图和数据队列以可视化优化进度

设置一个图形和一条动画线,以直观展示优化进程。

fig = figure(Visible="off",Name="Optimization Plot Function");
hline = animatedline(NaN,NaN, ...
        Color="none",Marker="o",MarkerFaceColor="b");

创建一个 DataQueue 对象,用于将进度数据从工作单元发送至客户端。

plotDq = parallel.pool.DataQueue;

要在 DataQueue 中绘制数据,请使用 afterEachDataQueue 每次接收数据时调用自定义绘图函数 plotSolverProgress。辅助函数 plotSolverProgress 定义在示例的末尾。

afterEach(plotDq,@(data) plotSolverProgress(hline,data{:}));

启动优化并发送停止消息

fminunc 创建一些选项,这些选项使用自定义输出函数 sendProgressAndStop 来发送进度信息并监听客户端指令。辅助函数 sendProgressAndStop 定义在示例的末尾。通过一个匿名函数将 plotDqstopPdq 对象传递给工作单元。

outFcn = @(x,v,s) sendProgressAndStop(x,v,s,plotDq,stopPdq);
opts = optimoptions("fminunc",OutputFcn=outFcn, ...
    Algorithm="quasi-newton");

安排一项 parfeval 计算任务,在工作单元上运行 fminunc 函数。

solverF = parfeval(@fminunc,4,fun,x0,opts);

显示该图以直观展示优化进程。

fig.Visible = "on";

parfeval 不会阻塞 MATLAB ®,因此您可以继续执行命令。在这种情况下,通过向工作单元发送一条消息来停止优化。

让优化运行十秒钟,然后使用 stopPdq PollableDataQueue 对象向工作单元发送一条 "stop" 消息。

pause(10)
send(stopPdq,"stop");

检索部分结果

获取 parfeval 的计算结果,并显示求解器的退出消息。当您通过输出函数停止优化时,fminunc 会返回最新的解、相应的目标函数值以及关于优化过程的中间信息。

[sol,fval,eflag,output] = fetchOutputs(solverF);
output.message
ans = 
'fminunc stopped by the output or plot function.'

参考资料

[1] 罗森布罗克,H. H.“一种寻找函数最大值或最小值的自动方法。”《计算机杂志》 第 3 卷第 3 期(1960 年):175–84. https://doi.org/10.1093/comjnl/3.3.175.

辅助函数

sendProgressAndStop 函数

sendProgressAndStop 函数使用 DataQueue 对象将进度数据发送给客户端,并使用 PollableDataQueue 对象检查来自客户端的指令。当客户端会话发送“停止”消息时,该函数会将 stop 标志更改为 true,从而停止优化。有关输出函数结构的信息,请参阅 输出函数和绘图函数语法 (Optimization Toolbox)

function stop = sendProgressAndStop(x,values,state,plotDq,stopPdq)
stop = false;
send(plotDq,{x,values,state});
pause(0.5) % Simulate an expensive iteration by pausing
in = poll(stopPdq);
if strcmp(in,"stop")
    stop = true;
end
end

plotSolverProgress 函数

plotSolverProgress 函数可在求解器执行过程中直观显示其进度。它使用一个 switch 语句来处理优化过程中的 inititerdone 状态,并据此更新图。有关绘图函数结构的信息,请参阅 输出函数和绘图函数语法 (Optimization Toolbox)

function plotSolverProgress(hline,~,optimValues,state)
switch state
    case 'init'
        clearpoints(hline)
        xlabel("Iteration");
        ylabel("Function value");
    case 'iter'
        addpoints(hline,optimValues.iteration,optimValues.fval);
        title("Current Function Value:",num2str(optimValues.fval));
        drawnow limitrate nocallbacks
    case 'done'
        title("Final Function Value:",num2str(optimValues.fval));
        drawnow limitrate nocallbacks
end
end

另请参阅

函数

主题