spmdparfor, и parfevalЧтобы запустить расчеты параллельно, можно использовать parfor, parfeval, parfevalOnAll, или spmd. Каждое построение использует различные концепции параллельного программирования. Если вы требуете, чтобы рабочие связались в течение расчета, использовать parfeval, parfevalOnAll, или spmd.
Использование parfeval или parfevalOnAll если ваш код может быть разделен в набор задач, где каждая задача может зависеть от выхода других задач.
Используйте spmd если вы требуете связи между рабочими во время расчета.
Расчеты с parfeval лучше всего представлены как график, похожий на плату Kanban с блокированием. Обычно результаты собраны от рабочих после того, как расчет будет завершен. Можно собрать результаты выполнения a parfeval операция при помощи afterEach или afterAll. Вы обычно используете результаты в дальнейших вычислениях.
Расчеты с spmd лучше всего представлены блок-схемой, похожей на рабочий процесс водопада. Рабочий пула, выполняющий spmd операторы называются лабораторией. Результаты могут быть забраны из лабораторий во время расчета. Иногда, лаборатории должны связаться с другими лабораториями, прежде чем они смогут закончить свой расчет.
Если вы не уверены, спросите себя следующее: в рамках моего кода параллели передачи, может каждый расчет быть завершенным без какой-либо связи между рабочими? Если да, использовать parfeval. В противном случае используйте spmd.
При выборе между parfor, parfeval, и spmd, рассмотрите, требует ли ваше вычисление синхронизации с клиентом.
parfor и spmd потребуйте синхронизации, и поэтому блокируйте вас от выполнения любых новых расчетов на клиенте MATLAB®. parfeval не требует синхронизации, таким образом, клиент свободен преследовать другую работу.
ProcessPoolВ этом примере вы выдерживаете сравнение, как быстрые функции работают на клиенте и на ProcessPool. Некоторые функции MATLAB используют многопоточность. Задачи, которые используют эти функции, выполняют лучше на нескольких потоках, чем один поток. Поэтому, если вы используете эти функции на машине со многими ядрами, локальный кластер может выполнить хуже, чем многопоточность на клиенте.
Функция поддержки clientFasterThanPool, перечисленный в конце этого примера, возвращает true если множества потоков выполнения выполняются быстрее на клиенте, чем parfor- цикл. Синтаксис совпадает с parfeval: используйте указатель на функцию в качестве первого аргумента, количества выходных параметров в качестве второго аргумента, и затем дайте все обязательные аргументы для функции.
Во-первых, создайте локальный ProcessPool.
p = parpool('local');Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 6).
Проверяйте как быстро eig функционируйте запуски при помощи clientFasterThanPool поддерживание функции. Создайте анонимную функцию с eig представлять ваш вызов функции.
[~, t_client, t_pool] = clientFasterThanPool(@(N) eig(randn(N)), 0, 500)
t_client = 22.6243
t_pool = 4.9334
Параллельный пул вычисляет ответ быстрее, чем клиент. Разделите t_client maxNumCompThreads найти время потраченным на поток на клиенте.
t_client/maxNumCompThreads
ans = 3.7707
Рабочие являются одним, распараллелил по умолчанию. Результат показывает, что время, потраченное на поток, подобно и на клиенте и на пуле как значение t_pool примерно 1,5 раза значение t_client/maxNumCompThreads. eig функция не извлекает выгоду из многопоточности.
Затем проверяйте как быстро lu функционируйте запуски при помощи clientFasterThanPool поддерживание функции.
[~, t_client, t_pool] = clientFasterThanPool(@(N) lu(randn(N)), 0, 500)
t_client = 1.0225
t_pool = 0.4693
Параллельный пул обычно вычисляет ответ быстрее, чем клиент, если ваша локальная машина имеет четыре или больше ядра. Разделите t_client maxNumCompThreads найти время потраченным на поток.
t_client/maxNumCompThreads
ans = 0.1704
Этот результат показывает, что время, потраченное на поток, находится намного меньше на клиенте, чем пул как значение t_pool примерно 3 раза значение t_client/maxNumCompThreads. Каждый поток используется в течение меньшего количества вычислительного времени, указывая на тот lu многопоточность использования.
Задайте функцию помощника
Функция поддержки clientFasterThanPool проверки, быстрее ли расчет на клиенте, чем на параллельном пуле. Это берет в качестве входа указателю на функцию fcn и переменное количество входных параметров (in1, in2, ...). clientFasterThanPool выполняет fcn(in1, in2, ...) и на клиенте и на активном параллельном пуле. Как пример, если вы хотите протестировать rand(500), ваш указатель на функцию должен быть в следующей форме:
fcn = @(N) rand(N);
Затем используйте clientFasterThanPool(fcn,500).
function [result, t_multi, t_single] = clientFasterThanPool(fcn,numout,varargin) % Preallocate cell array for outputs outputs = cell(numout); % Client tic for i = 1:200 if numout == 0 fcn(varargin{:}); else [outputs{1:numout}] = fcn(varargin{:}); end end t_multi = toc; % Parallel pool vararginC = parallel.pool.Constant(varargin); tic parfor i = 1:200 % Preallocate cell array for outputs outputs = cell(numout); if numout == 0 fcn(vararginC.Value{:}); else [outputs{1:numout}] = fcn(vararginC.Value{:}); end end t_single = toc; % If multhreading is quicker, return true result = t_single > t_multi; end
parfor, parfeval, и spmdИспользуя spmd может быть медленнее или быстрее, чем использование parfor- циклы или parfeval, В зависимости от типа расчета. Издержки влияют на относительную эффективность parfor- циклы, parfeval, и spmd.
Для набора задач, parfor и parfeval обычно выполняйте лучше, чем spmd при этих условиях.
Вычислительное время, потраченное на задачу, не детерминировано.
Вычислительное время, потраченное на задачу, не универсально.
Данные, возвращенные в каждую задачу, малы.
Используйте parfeval когда:
Вы хотите запустить расчеты в фоновом режиме.
Каждая задача зависит от других задач.
В этом примере вы исследуете скорость, на которой операции над матрицей могут быть выполнены при использовании parfor- цикл, parfeval, и spmd.
Во-первых, создайте локальный параллельный пул p.
p = parpool('local');Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 6).
Вычислите случайные матрицы
Исследуйте скорость, на которой случайные матрицы могут быть сгенерированы при помощи parfor- цикл, parfeval, и spmd. Определите номер испытаний (n) и матричный размер (для m- m матрица). Увеличение числа испытаний улучшает статистику, используемую в более позднем анализе, но не влияет на само вычисление.
m =1000; n =
20;
Затем используйте parfor- цикл, чтобы выполнить rand(m) однажды для каждого рабочего. Время каждый n испытания.
parforTime = zeros(n,1); for i = 1:n tic; mats = cell(1,p.NumWorkers); parfor N = 1:p.NumWorkers mats{N} = rand(m); end parforTime(i) = toc; end
Затем используйте parfeval выполнить rand(m) однажды для каждого рабочего. Время каждый n испытания.
parfevalTime = zeros(n,1); for i = 1:n tic; f(1:p.NumWorkers) = parallel.FevalFuture; for N = 1:p.NumWorkers f(N) = parfeval(@rand,1,m); end mats = fetchOutputs(f, "UniformOutput", false)'; parfevalTime(i) = toc; clear f end
Наконец, используйте spmd выполнить rand(m) однажды для каждой лаборатории. Для получения дополнительной информации на лабораториях и как выполнить команды на них с spmd, смотрите Запуск Одна Программы на Нескольких Наборах данных. Время каждый n испытания.
spmdTime = zeros(n,1); for i = 1:n tic; spmd e = rand(m); end eigenvals = {e{:}}; spmdTime(i) = toc; end
Используйте rmoutliers удалить выбросы из каждого из испытаний. Затем используйте boxplot сравнить времена.
% Hide outliers boxData = rmoutliers([parforTime parfevalTime spmdTime]); % Plot data boxplot(boxData, 'labels',{'parfor','parfeval','spmd'}, 'Symbol','') ylabel('Time (seconds)') title('Make n random matrices (m by m)')

Как правило, spmd требует больше служебного на оценку, чем parfor или parfeval. Поэтому в этом случае, использование parfor- цикл или parfeval более эффективно.
Вычислите сумму случайных матриц
Затем вычислите сумму случайных матриц. Можно сделать это при помощи переменной сокращения с parfor- цикл, сумма после расчетов с parfeval, или gplus с spmd. Снова, определите номер испытаний (n) и матричный размер (для m- m матрица).
m =1000; n =
20;
Затем используйте parfor- цикл, чтобы выполнить rand(m) однажды для каждого рабочего. Вычислите сумму с переменной сокращения. Время каждый n испытания.
parforTime = zeros(n,1); for i = 1:n tic; result = 0; parfor N = 1:p.NumWorkers result = result + rand(m); end parforTime(i) = toc; end
Затем используйте parfeval выполнить rand(m) однажды для каждого рабочего. Используйте fetchOutputs на всех матрицах затем используйте sum. Время каждый n испытания.
parfevalTime = zeros(n,1); for i = 1:n tic; f(1:p.NumWorkers) = parallel.FevalFuture; for N = 1:p.NumWorkers f(N) = parfeval(@rand,1,m); end result = sum(fetchOutputs(f)); parfevalTime(i) = toc; clear f end
Наконец, используйте spmd выполнить rand(m) однажды для каждой лаборатории. Используйте gplus суммировать все матрицы. Чтобы отправить результат только первой лаборатории, установите дополнительный targetlab аргумент к 1. Время каждый n испытания.
spmdTime = zeros(n,1); for i = 1:n tic; spmd r = gplus(rand(m), 1); end result = r{1}; spmdTime(i) = toc; end
Используйте rmoutliers удалить выбросы из каждого из испытаний. Затем используйте boxplot сравнить времена.
% Hide outliers boxData = rmoutliers([parforTime parfevalTime spmdTime]); % Plot data boxplot(boxData, 'labels',{'parfor','parfeval','spmd'}, 'Symbol','') ylabel('Time (seconds)') title('Sum of n random matrices (m by m)')

Для этого вычисления, spmd значительно быстрее, чем parfor- цикл или parfeval. Когда вы используете переменные сокращения в parfor- цикл, вы широковещательно передаете результат каждой итерации parfor- цикл всем рабочим. В отличие от этого, spmd вызовы gplus только однажды, чтобы сделать глобальную операцию сокращения, требуя меньше служебного. По сути, издержки для части сокращения вычисления для spmd, и для parfor.