exponenta event banner

Масштабирование с рабочего стола на кластер

В этом примере показано, как разработать параллельный код MATLAB ® на локальном компьютере и масштабировать его до кластера. Кластеры предоставляют больше вычислительных ресурсов для ускорения и распределения вычислений. Код можно запускать в интерактивном режиме параллельно на локальном компьютере, затем в кластере без изменения кода. По завершении создания прототипа кода на локальном компьютере можно выгрузить вычисления в кластер с помощью пакетных заданий. Таким образом, можно закрыть MATLAB и получить результаты позже .

Разработка алгоритма

Начните с создания прототипа алгоритма на локальном компьютере. Пример использует целочисленную факторизацию в качестве примера проблемы. Это вычислительно интенсивная задача, где сложность факторизации возрастает с величиной числа. Для факторизации последовательности целых чисел используется простой алгоритм.

Создайте вектор простых чисел с 64-разрядной точностью и произвольно умножьте пары простых чисел, чтобы получить большие составные числа. Создайте массив для хранения результатов каждой факторизации. Код в каждом из следующих разделов в этом примере может занять более 20 мин. Чтобы сделать его быстрее, уменьшите рабочую нагрузку, используя меньшее количество простых чисел, например 2^19. Выполнить с 2^21 для просмотра оптимальных окончательных графиков.

primeNumbers = primes(uint64(2^21));
compositeNumbers = primeNumbers.*primeNumbers(randperm(numel(primeNumbers)));
factors = zeros(numel(primeNumbers),2);

Используйте цикл для деления каждого составного числа и измерения времени, которое занимает вычисление.

tic;
for idx = 1:numel(compositeNumbers)
    factors(idx,:) = factor(compositeNumbers(idx));
end
toc
Elapsed time is 684.464556 seconds.

Выполнение кода на локальном параллельном пуле

Parallel Computing Toolbox™ позволяет масштабировать рабочий процесс, работая на нескольких рабочих в параллельном пуле. Итерации в предыдущем for циклы независимы, поэтому можно использовать parfor цикл для распределения итераций по нескольким работникам. Просто преобразите for цикл в parfor цикл. Затем запустите код и измерьте общее время вычислений. Код запускается в параллельном пуле без дальнейших изменений, и работники отправляют вычисления обратно в локальную рабочую область. Поскольку рабочая нагрузка распределена между несколькими работниками, время вычисления меньше.

tic;
parfor idx = 1:numel(compositeNumbers)
    factors(idx,:) = factor(compositeNumbers(idx));
end
toc
Elapsed time is 144.550358 seconds.

При использовании parfor и у вас есть панель инструментов Parallel Computing Toolbox, MATLAB автоматически запускает параллельный пул работников. Запуск параллельного пула занимает некоторое время. В этом примере показан второй запуск с уже запущенным пулом.

Профиль кластера по умолчанию: 'local'. Можно проверить, установлен ли этот профиль по умолчанию на вкладке Главная страница MATLAB (Parallel > Select a Default Cluster). Если этот профиль включен, MATLAB создает работников на компьютере для параллельного пула. При использовании 'local' профиль, MATLAB, по умолчанию, запускает столько работников, сколько физических ядер в машине, вплоть до предпочтительного количества работников. Управлять поведением параллели можно с помощью настроек параллелизма. На вкладке ГЛАВНАЯ СТРАНИЦА (MATLAB Home) выберите Параллельный (Parallel) > Параллельные настройки (Parallel Preferences).

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

numWorkers = [1 2 4 6];
tLocal = zeros(size(numWorkers));

Используйте цикл для итерации максимального числа работников и выполните предыдущий код. Чтобы ограничить число работников, используйте второй входной аргумент parfor.

for w = 1:numel(numWorkers)
    tic;
    parfor (idx = 1:numel(compositeNumbers), numWorkers(w))
        factors(idx,:) = factor(compositeNumbers(idx));
    end
    tLocal(w) = toc;
end

Вычислите ускорение, вычисляя соотношение между временем вычисления одного работника и временем вычисления каждого максимального числа работников. Чтобы визуализировать, как вычисления увеличиваются с увеличением числа работников, постройте график ускорения по отношению к количеству работников. Заметьте, что скорость увеличивается с увеличением числа работников. Однако масштабирование не является совершенным из-за служебных данных, связанных с параллелизацией.

f = figure;
speedup = tLocal(1)./tLocal;
plot(numWorkers, speedup);
title('Speedup with the number of workers');
xlabel('Number of workers');
xticks(numWorkers);
ylabel('Speedup');

После завершения вычислений удалите текущий параллельный пул, чтобы создать новый пул для кластера. Текущий параллельный пул можно получить с помощью gcp функция.

delete(gcp);

Настройка кластера

Если вычислительная задача слишком велика или слишком медлена для локального компьютера, можно выгрузить расчет в кластер на месте или в облаке. Перед запуском следующих разделов необходимо получить доступ к кластеру. На вкладке Главная страница MATLAB перейдите в раздел Параллельный > Обнаружение кластеров, чтобы узнать, есть ли у вас доступ к кластеру с параллельным Server™ MATLAB. Дополнительные сведения см. в разделе Обнаружение кластеров.

Если у вас нет доступа к кластеру, необходимо настроить доступ к нему перед запуском следующих разделов. В MATLAB можно создавать кластеры в облачном сервисе, например Amazon AWS, непосредственно с рабочего стола MATLAB. На вкладке Главная в меню Параллельный выберите Создать кластеры и управление ими. В диспетчере профилей кластера щелкните Создать облачный кластер. Дополнительные сведения о масштабировании до облачной среды см. в разделе Начало работы с облачным центром. Дополнительные сведения о параметрах масштабирования на кластер в сети см. в разделе Начало работы с параллельным сервером MATLAB (MATLAB Parallel Server).

После настройки профиля кластера его свойства можно изменить в меню «Параллельный» > «Создание кластеров и управление ими». Дополнительные сведения см. в разделах Обнаружение кластеров и Использование профилей кластеров. На следующем рисунке показан профиль кластера в диспетчере профилей кластера:

Запуск кода в параллельном пуле кластера

Если вы хотите запустить параллельные функции в кластере по умолчанию, установите профиль кластера как профиль по умолчанию в разделе Параллельный > Выбрать кластер по умолчанию:

Для определения кластера можно также использовать программный подход. Для этого запустите параллельный пул в кластере, указав имя профиля кластера в parpool команда. В следующем коде замените MyCluster с именем профиля кластера. Также укажите число работников со вторым входным аргументом.

parpool('MyCluster',64);
Starting parallel pool (parpool) using the 'MyCluster' profile ...
connected to 64 workers.

Как и прежде, измерьте ускорение с количеством работников, выполнив один и тот же код несколько раз, и ограничив максимальное количество работников. Поскольку кластер в этом примере допускает больше работников, чем локальная установка, numWorkers может содержать больше значений. Если вы запускаете этот код, parfor Теперь цикл выполняется в кластере.

numWorkers = [1 2 4 6 16 32 64];
tCluster = zeros(size(numWorkers));

for w = 1:numel(numWorkers)
    tic;
    parfor (idx = 1:numel(compositeNumbers), numWorkers(w))
        factors(idx,:) = factor(compositeNumbers(idx));
    end
    tCluster(w) = toc;
end

Вычислите ускорение и постройте график по количеству работников, чтобы визуализировать, как вычисления увеличиваются с увеличением числа работников. Сравните результаты с результатами локальной настройки. Заметьте, что скорость увеличивается с увеличением числа работников. Однако масштабирование не является совершенным из-за служебных данных, связанных с параллелизацией.

figure(f);
hold on
speedup = tCluster(1)./tCluster;
plot(numWorkers, speedup);
title('Speedup with the number of workers');
xlabel('Number of workers');
xticks(numWorkers(2:end));
ylabel('Speedup');

После завершения вычислений удалите текущий параллельный пул.

delete(gcp);

Разгрузка и масштабирование вычислений с помощью batch

После создания прототипа и выполнения в интерактивном режиме можно использовать пакетные задания для разгрузки выполнения длительных вычислений в фоновом режиме с пакетной обработкой. Вычисление происходит в кластере, и вы можете закрыть MATLAB и получить результаты позже.

Используйте batch для отправки пакетного задания в кластер. Можно поместить содержимое алгоритма в сценарий и использовать batch функция, чтобы отправить его. Например, сценарий myParallelAlgorithm выполняет простой тест на основе целочисленной задачи факторизации, показанной в этом примере. Сценарий измеряет время вычисления нескольких сложных проблем с разным количеством работников.

Обратите внимание, что при отправке файла сценария с помощью batchMATLAB переносит все переменные рабочей области в кластер, даже если сценарий не использует их. Большая рабочая область отрицательно влияет на время передачи данных. Рекомендуется преобразовать сценарий в файл функций, чтобы избежать таких накладных расходов на связь. Это можно сделать, просто добавив строку функции в начале сценария. Чтобы изучить, как преобразовать myParallelAlgorithm в функцию, см. myParallelAlgorithmFcn.

Следующий код передает myParallelAlgorithmFcn как пакетное задание. myParallelAlgorithmFcn возвращает два выходных аргумента, numWorkers и time, и необходимо указать 2 в качестве входного аргумента количества выходов. Потому что код нуждается в параллельном пуле для parfor loop, используйте 'Pool' пара имя-значение в batch для указания количества работников. Кластер использует дополнительный работник для выполнения самой функции. По умолчанию batch изменяет текущую папку работников в кластере на текущую папку клиента MATLAB. Может быть полезно управлять текущей папкой. Например, если кластер использует другую файловую систему, и поэтому пути отличаются, например, при отправке данных с клиентского компьютера Windows в кластер Linux. Задать пару имя-значение 'CurrentFolder' в папку по вашему выбору или в '.' во избежание изменения папки работников.

totalNumberOfWorkers = 65;
cluster = parcluster('MyCluster');
job = batch(cluster,'myParallelAlgorithmFcn',2,'Pool',totalNumberOfWorkers-1,'CurrentFolder','.');

Чтобы отслеживать состояние задания после его отправки, откройте Монитор заданий параллельно > Контролировать задания. Когда вычисления начинаются в кластере, состояние задания меняется на running:

MATLAB можно закрыть после отправки задания. При повторном открытии MATLAB монитор заданий отслеживает задание и может взаимодействовать с ним, если щелкнуть его правой кнопкой мыши. Например, чтобы извлечь объект задания, выберите Показать подробности (Show Details), а чтобы перенести выходные данные пакетного задания в рабочую область, выберите Получить выходные данные (Fetch Outputs).

Кроме того, если требуется заблокировать MATLAB до завершения задания, используйте wait в объекте задания.

wait(job);

Для передачи выходных данных функции из кластера используйте fetchOutputs функция.

outputs = fetchOutputs(job);
numWorkers = outputs{1};
time = outputs{2};

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

figure
speedup = time(1,:)./time;
plot(numWorkers,speedup);
legend('Problem complexity 1','Problem complexity 2','Problem complexity 3','Problem complexity 4','Location','northwest');
title('Speedup vs complexity');
xlabel('Number of workers');
xticks(numWorkers(2:end));
ylabel('Speedup');

См. также

| | |

Связанные примеры

Подробнее