8.3 KiB
Лабораторная работа 4
Задание
Разработка распределенного приложения с использованием платформы Apache Ignite. Необходимо разработать параллельный вариант алгоритма с применением подхода Grid Gain и платформа Apache Ignite, замерить время его работы.
Вариант: "Упорядочить строки матрицы по убыванию первых элементов."
Описание работы программы
- Инициализация Ignite: Запускает Ignite-кластер, используя конфигурационный файл
conf.xml. - Генерация матрицы: Создает квадратную матрицу заданного размера (из аргументов командной строки).
- Распределенная сортировка матрицы:
- Использует Ignite для распределенного выполнения задачи
MatrixSortingTask. - Задача
MatrixSortingTaskразделяет работу на подзадачи (MatrixSortingJob), распределяя обработку строк матрицы между узлами кластера.
- Использует Ignite для распределенного выполнения задачи
- Разделение задачи(
split)- Игнайт автоматически определяет количество узлов (gridSize).
- Матрица разбивается на блоки строк, каждый из которых обрабатывается отдельной подзадачей (MatrixSortingJob).
- Параллельная сортировка (
execute)- Каждый узел получает свой диапазон строк, сортирует их по первому элементу (по убыванию) и возвращает результат.
- Объединение результатов (
reduce)- Главный узел собирает все отсортированные блоки и выполняет финальную сортировку для получения итоговой матрицы.
- Вывод результата:
- Если размер матрицы меньше 10x10, выводит отсортированную матрицу в консоль.
- В противном случае выводит сообщение о завершении сортировки.
- Замеряет и выводит время выполнения (duration).
Описание кода
public static void main(String[] args) {
String workingDir = System.getProperty("user.dir") + File.separator + "conf.xml";
Path path = Paths.get(workingDir);
int size = Integer.parseInt(args[args.length - 1]);
try (Ignite ignite = Ignition.start(workingDir)) {
int[][] matrix = new int[size][size];
Random r = new Random();
}
Основной метод программы, который:
- Загружает конфигурацию Ignite из файла conf.xml
- Получает размер матрицы из аргументов командной строки
- Инициализирует Ignite-кластер
- Создает матрицу заданного размера и заполняет случайными числами
public static class MatrixSortingTask extends ComputeTaskSplitAdapter<int[][], int[][]> {
@Override
protected List<ComputeJob> split(int gridSize, int[][] matrix) {
List<ComputeJob> jobs = new ArrayList<>();
int batchSize = Math.max(1, matrix.length / gridSize);
Класс задачи, который Разделяет матрицу на части по количеству доступных узлов (gridSize) и создает подзадачи (MatrixSortingJob) для обработки каждой части.
public static class MatrixSortingJob implements ComputeJob {
@Override
public int[][] execute() {
List<int[]> rows = new ArrayList<>();
for (int[] row : part) {
rows.add(row);
}
Collections.sort(rows, (row1, row2) -> Integer.compare(row2[0], row1[0]));
Класс подзадачи, который получает часть для обработки, сортирует и возвращает отсортированную часть.
@Override
public int[][] reduce(List<ComputeJobResult> results) {
List<int[]> sortedRows = new ArrayList<>();
for (ComputeJobResult res : results) {
int[][] part = res.getData();
Collections.sort(sortedRows, (row1, row2) -> Integer.compare(row2[0], row1[0]));
}
return sortedRows.toArray(new int[0][]);
}
Метод получающий результаты со всех узлов, выполняет финальную сортировку объединенной матрицы.
Запуск приложения
- На обоих контейнерах должен быть установлен Apache Ignite.
wget https://dlcdn.apache.org/ignite/2.17.0/apache-ignite-2.17.0-bin.zip unzip apache-ignite-2.17.0-bin.zip - На первом контейнере должен быть jar файл в одной папке с conf.xml, на втором в apache-ignite-2.17.0-bin/config должен находиться наш myConf.xml
- Переходим на второй контейнер, который без jar файла и переходим в директорию apache-ignite-2.17.0-bin/bin, выполняем следующую команду:
Выбираем myConf.xml
ignite.sh -i - На контейнере с jar файлом запускаем программу
java -jar sspr4-1.0-SNAPSHOT.jar SIZE
Основные технологии
- Maven
- Apache Ignite
- Java 11
Результат работы программы
Запуск:
java -jar sspr4-1.0-SNAPSHOT.jar 5
Вывод в первом контейнере:
Original matrix:
29 75 96 81 52
21 97 49 1 72
51 66 20 60 71
0 20 30 70 66
49 72 49 91 11
[MAIN] Created job for rows 0 to 1
[MAIN] Created job for rows 2 to 4
[Node-52c56677] Processing rows 0 to 1
[Node-52c56677] Part before sorting:
29 75 96 81 52
21 97 49 1 72
[Node-52c56677] Part after sorting:
29 75 96 81 52
21 97 49 1 72
Sorted matrix (by first element in descending order):
51 66 20 60 71
49 72 49 91 11
29 75 96 81 52
21 97 49 1 72
0 20 30 70 66
Execution time: 109 ms
[12:04:46] Ignite node stopped OK [name=my-cluster, uptime=00:00:00.327]
Вывод в втором контейенере:
[Node-85bfc0d0] Processing rows 2 to 4
[Node-85bfc0d0] Part before sorting:
51 66 20 60 71
0 20 30 70 66
49 72 49 91 11
[Node-85bfc0d0] Part after sorting:
51 66 20 60 71
49 72 49 91 11
0 20 30 70 66
Были проведены замеры работы программы на разных объёмах данных:
Замеры с использованием двух узлов:
- size 1000: 171 ms
- size 3000: 967 ms
- size 5000: 1881 ms
- size 7000: 4744 ms
Замеры с выполнением на одном узле:
- size 1000: 32 ms
- size 3000: 29 ms
- size 5000: 50 ms
- size 7000: 68 ms
Вывод
Из полученных результатов можно сделать вывод, что в нашем случае, распределение вычислений между контейенерами привело к значительному замедлению во всех случаях. Накладные расходы на координацию между узлами занимают гораздо большее время, чем сам процесс сортировки.