График во время протягивания параметра с 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;

Создайте 2-D сетку параметров при помощи 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 функция. The 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')

Если вашему параметру sweep нужно больше вычислительных ресурсов и у вас есть доступ к кластеру, можно масштабировать 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

См. также

| | |

Похожие темы