spmd
parfor
, и 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
.