使用 parfor
进行参数扫描时的绘图
并行执行参数扫描,并在并行计算过程中绘制进度。
您可以使用 DataQueue
来监视并行池计算期间的结果。您还可以将 DataQueue
与并行语言功能(例如 parfor
、parfeval
和 spmd
)一起使用。
该示例展示了如何对经典系统范德波尔振荡器执行参数扫描。该系统可以表示为一组依赖于两个范德波尔振荡器参数 和 的 ODE:
您可以使用 parfor
循环对参数 和 执行并行参数扫描,以找出改变它们时 的平均周期。下面的动画展示了此示例在本地集群中的执行。
设置参数扫描值
定义要探索的参数的值范围。创建一个网格来解释参数的不同组合。
gridSize = 6; mu = linspace(100, 150, gridSize); nu = linspace(0.5, 2, gridSize); [M,N] = meshgrid(mu,nu);
准备表面图来可视化结果
声明一个变量来存储扫描结果。使用 nan
进行预分配,以避免绘制初始表面。创建曲面图来可视化每个参数组合的扫描结果。准备标题、标签和限制等设置。
Z = nan(size(N)); c = surf(M, N, Z); xlabel('\mu Values','Interpreter','Tex') ylabel('\nu Values','Interpreter','Tex') zlabel('Mean Period of y') view(137, 30) axis([100 150 0.5 2 0 500]);
设置 DataQueue 以在参数扫描期间获取结果
创建一个 DataQueue
来将中间结果从工作进程发送到客户端。使用 afterEach
函数在客户端中定义一个回调,每次工作进程发送当前结果时更新表面。
D = parallel.pool.DataQueue; D.afterEach(@(x) updateSurface(c, x));
执行参数扫描并绘制结果
使用 parfor
执行并行参数扫描。指导工作进程对网格中每个参数组合求解系统,并计算平均周期。当工作进程完成计算时立即将每次迭代的结果发送回客户端。
parfor ii = 1:numel(N) [t, y] = solveVdp(M(ii), N(ii)); l = islocalmax(y(:, 2)); send(D, [ii mean(diff(t(l)))]); end
Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 6).
扩展到集群
如果您可以访问集群,那么您可以扩大您的计算规模。为此,请删除前一个 parpool
,然后使用更大集群的配置文件打开一个新的。下面的代码显示了一个名为 'MyClusterInTheCloud'
的集群配置文件。要自己运行此代码,您必须将 'MyClusterInTheCloud'
替换为您的集群配置文件的名称。调整工作进程数量。该示例有 4 个工作进程。通过增加网格的大小来增加整体计算的规模。
gridSize = 25; delete(gcp('nocreate')); parpool('MyClusterInTheCloud',4);
Starting parallel pool (parpool) using the 'MyClusterInTheCloud' profile ... Connected to the parallel pool (number of workers: 4).
如果在设置集群配置文件后再次运行参数扫描代码,则集群中的工作进程将计算并在结果可用时将结果发送到 MATLAB 客户端。下面的动画展示了此示例在集群中的执行。
辅助函数
创建一个辅助函数来定义方程组,并在其上应用求解器。
function [t, y] = solveVdp(mu, nu) f = @(~,y) [nu*y(2); mu*(1-y(1)^2)*y(2)-y(1)]; [t,y] = ode23s(f,[0 20*mu],[2; 0]); end
为 DataQueue 声明一个函数,使用来自工作进程的结果来更新图表。
function updateSurface(s, d) s.ZData(d(1)) = d(2); drawnow('limitrate'); end