Постройте во время развертки параметра с parfeval

В этом примере показано, как выполнить параллельную развертку параметра с parfeval и передайте результаты обратно во время расчетов с DataQueue объект. parfeval не делает блока MATLAB, таким образом, можно продолжить работать, в то время как расчеты происходят.

Пример выполняет развертку параметра в системе Лоренца обыкновенных дифференциальных уравнений на параметрах σ и ρ, и показывает хаотическую природу этой системы.

ddtx=σ(y-z)ddty=x(ρ-z)-yddtz=xy-βx

Создайте сетку параметра

Задайте область значений параметров, которые вы хотите исследовать в развертке параметра.

gridSize = 40;
sigma = linspace(5, 45, gridSize);
rho = linspace(50, 100, gridSize);
beta = 8/3;

Создайте 2D сетку параметров при помощи meshgrid функция.

[rho,sigma] = meshgrid(rho,sigma);

Создайте объект фигуры и установите 'Visible' к true так, чтобы это открылось в новом окне, за пределами live скрипта. Чтобы визуализировать результаты развертки параметра, создайте объемную поверхностную диаграмму. Обратите внимание на то, что инициализация Z компонент поверхности с NaN создает пустой график.

figure('Visible',true);
surface = surf(rho,sigma,NaN(size(sigma)));
xlabel('\rho','Interpreter','Tex')
ylabel('\sigma','Interpreter','Tex')

Настройте параллельную среду

Создайте пул параллельных рабочих при помощи parpool функция.

parpool;
Starting parallel pool (parpool) using the 'local' profile ...
Connected to the parallel pool (number of workers: 6).

Чтобы отправить данные от рабочих, создайте DataQueue объект. Настройте функцию, которая обновляет объемную поверхностную диаграмму каждый раз, когда рабочий отправляет данные при помощи afterEach функция. updatePlot функция является функцией, определяемой поддержки в конце примера.

Q = parallel.pool.DataQueue;
afterEach(Q,@(data) updatePlot(surface,data));

Выполните параллельную развертку параметра

После того, как вы зададите параметры, можно выполнить параллельную развертку параметра.

parfeval работает более эффективно, когда вы распределяете рабочую нагрузку. Чтобы распределить рабочую нагрузку, сгруппируйте параметры, чтобы исследовать в разделы. В данном примере разделите в универсальные разделы размера step при помощи оператора двоеточия (:). Полученный массив partitions содержит контуры разделов. Обратите внимание на то, что необходимо добавить конечную точку последнего раздела.

step = 100;
partitions = [1:step:numel(sigma), numel(sigma)+1]
partitions = 1×17

           1         101         201         301         401         501         601         701         801         901        1001        1101        1201        1301        1401        1501        1601

Для лучшей эффективности попытайтесь разделить в разделы, которые являются:

  • Достаточно большой, что время вычисления является большим по сравнению с издержками планирования раздела.

  • Достаточно маленький, что существует достаточно разделов, чтобы заставить всех рабочих напряженно трудиться.

Чтобы представлять функциональное выполнение на параллельных рабочих и содержать их результаты, используйте будущие объекты.

f(1:numel(partitions)-1) = parallel.FevalFuture;

Разгрузите расчеты, чтобы быть параллельными рабочим при помощи parfeval функция. parameterSweep функция, определяемая помощника в конце этого скрипта, который решает систему Лоренца на разделе параметров, чтобы исследовать. Это имеет один выходной аргумент, таким образом, необходимо задать 1 как количество выходных параметров в parfeval.

for ii = 1:numel(partitions)-1
    f(ii) = parfeval(@parameterSweep,1,partitions(ii),partitions(ii+1),sigma,rho,beta,Q);
end

parfeval не делает блока MATLAB, таким образом, можно продолжить работать, в то время как расчеты происходят. Рабочие вычисляют параллельно и отправляют промежуточные результаты через DataQueue как только они становятся доступными.

Если вы хотите с блоком MATLAB до parfeval завершается, используйте wait функция на будущих объектах. Используя wait функция полезна, когда последующий код зависит от завершения parfeval.

wait(f);

После parfeval закончил расчеты, wait концы и вы можете выполнить больше кода. Например, постройте контур получившейся поверхности. Используйте fetchOutputs функция, чтобы получить результаты, сохраненные в будущих объектах.

results = reshape(fetchOutputs(f),gridSize,[]);
contourf(rho,sigma,results)
xlabel('\rho','Interpreter','Tex')
ylabel('\sigma','Interpreter','Tex')

Если вашей развертке параметра нужно больше вычислительных ресурсов, и у вас есть доступ к кластеру, можно увеличить parfeval расчеты. Для получения дополнительной информации смотрите, Масштабируют от Рабочего стола до Кластера.

Определение функций помощника

Задайте функцию помощника, которая решает систему Лоренца на разделе параметров, чтобы исследовать. Отправьте промежуточные результаты клиенту MATLAB при помощи send функция на DataQueue объект.

function results = parameterSweep(first,last,sigma,rho,beta,Q)
    results = zeros(last-first,1);
    for ii = first:last-1
        lorenzSystem = @(t,a) [sigma(ii)*(a(2) - a(1)); a(1)*(rho(ii) - a(3)) - a(2); a(1)*a(2) - beta*a(3)];
        [t,a] = ode45(lorenzSystem,[0 100],[1 1 1]);
        result = a(end,3);
        send(Q,[ii,result]);
        results(ii-first+1) = result;
    end
end

Задайте другую функцию помощника, которая обновляет объемную поверхностную диаграмму, когда новые данные прибывают.

function updatePlot(surface,data)
    surface.ZData(data(1)) = data(2);
    drawnow('limitrate');
end

Смотрите также

| | |

Похожие темы