diff --git a/pyzhov_egor_lab_4/.gitignore b/pyzhov_egor_lab_4/.gitignore
new file mode 100644
index 0000000..d048d4b
--- /dev/null
+++ b/pyzhov_egor_lab_4/.gitignore
@@ -0,0 +1,40 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+!conf.xml
+!myConf.xml
+!pom.xml
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/pyzhov_egor_lab_4/conf.xml b/pyzhov_egor_lab_4/conf.xml
new file mode 100644
index 0000000..8cd816d
--- /dev/null
+++ b/pyzhov_egor_lab_4/conf.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pyzhov_egor_lab_4/myConf.xml b/pyzhov_egor_lab_4/myConf.xml
new file mode 100644
index 0000000..8273f6f
--- /dev/null
+++ b/pyzhov_egor_lab_4/myConf.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+ 192.168.17.117:47500
+ 192.168.17.118:47500
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pyzhov_egor_lab_4/pom.xml b/pyzhov_egor_lab_4/pom.xml
new file mode 100644
index 0000000..8d3acda
--- /dev/null
+++ b/pyzhov_egor_lab_4/pom.xml
@@ -0,0 +1,50 @@
+
+ 4.0.0
+
+ org.urlshort
+ sspr4
+ 1.0-SNAPSHOT
+ jar
+
+ lab4
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
+
+ org.apache.ignite
+ ignite-core
+ 2.17.0
+
+
+ org.apache.ignite
+ ignite-indexing
+ 2.17.0
+
+
+ org.apache.ignite
+ ignite-spring
+ 2.17.0
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 2.7.18
+
+
+
+ repackage
+
+
+
+
+
+
+
diff --git a/pyzhov_egor_lab_4/readme.md b/pyzhov_egor_lab_4/readme.md
new file mode 100644
index 0000000..fa68117
--- /dev/null
+++ b/pyzhov_egor_lab_4/readme.md
@@ -0,0 +1,171 @@
+# Лабораторная работа 4
+
+## Задание
+
+Разработка распределенного приложения с использованием платформы Apache Ignite.
+Необходимо разработать параллельный вариант алгоритма с применением подхода Grid
+Gain и платформа Apache Ignite, замерить время его работы.
+
+**Вариант:** "Упорядочить строки матрицы по убыванию первых элементов."
+
+## Описание работы программы
+
+1. **Инициализация Ignite:** Запускает Ignite-кластер, используя конфигурационный файл `conf.xml`.
+2. **Генерация матрицы:** Создает квадратную матрицу заданного размера (из аргументов командной строки).
+3. **Распределенная сортировка матрицы:**
+ * Использует Ignite для распределенного выполнения задачи `MatrixSortingTask`.
+ * Задача `MatrixSortingTask` разделяет работу на подзадачи (`MatrixSortingJob`), распределяя обработку строк матрицы между узлами кластера.
+4. **Разделение задачи(`split`)**
+ * Игнайт автоматически определяет количество узлов (gridSize).
+ * Матрица разбивается на блоки строк, каждый из которых обрабатывается отдельной подзадачей (MatrixSortingJob).
+5. **Параллельная сортировка (`execute`)**
+ * Каждый узел получает свой диапазон строк, сортирует их по первому элементу (по убыванию) и возвращает результат.
+6. **Объединение результатов (`reduce`)**
+ * Главный узел собирает все отсортированные блоки и выполняет финальную сортировку для получения итоговой матрицы.
+7. **Вывод результата:**
+ * Если размер матрицы меньше 10x10, выводит отсортированную матрицу в консоль.
+ * В противном случае выводит сообщение о завершении сортировки.
+ * Замеряет и выводит время выполнения (duration).
+## Описание кода
+```java
+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-кластер
+* Создает матрицу заданного размера и заполняет случайными числами
+
+
+```java
+public static class MatrixSortingTask extends ComputeTaskSplitAdapter {
+ @Override
+ protected List split(int gridSize, int[][] matrix) {
+ List jobs = new ArrayList<>();
+ int batchSize = Math.max(1, matrix.length / gridSize);
+```
+Класс задачи, который Разделяет матрицу на части по количеству доступных узлов (gridSize) и создает подзадачи (MatrixSortingJob) для обработки каждой части.
+
+```java
+public static class MatrixSortingJob implements ComputeJob {
+ @Override
+ public int[][] execute() {
+ List rows = new ArrayList<>();
+ for (int[] row : part) {
+ rows.add(row);
+ }
+ Collections.sort(rows, (row1, row2) -> Integer.compare(row2[0], row1[0]));
+```
+Класс подзадачи, который получает часть для обработки, сортирует и возвращает отсортированную часть.
+
+```java
+@Override
+public int[][] reduce(List results) {
+ List 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][]);
+}
+```
+Метод получающий результаты со всех узлов, выполняет финальную сортировку объединенной матрицы.
+
+
+## Запуск приложения
+1) На обоих контейнерах должен быть установлен Apache Ignite.
+ ```bush
+ wget https://dlcdn.apache.org/ignite/2.17.0/apache-ignite-2.17.0-bin.zip
+ unzip apache-ignite-2.17.0-bin.zip
+ ```
+2) На первом контейнере должен быть jar файл в одной папке с conf.xml, на втором в apache-ignite-2.17.0-bin/config должен находиться наш myConf.xml
+3) Переходим на второй контейнер, который без jar файла и переходим в директорию apache-ignite-2.17.0-bin/bin, выполняем следующую команду:
+ ```bash
+ ignite.sh -i
+ ```
+ Выбираем myConf.xml
+4) На контейнере с jar файлом запускаем программу
+ ```bash
+ java -jar sspr4-1.0-SNAPSHOT.jar SIZE
+ ```
+
+## Основные технологии
+
+- **Maven**
+- **Apache Ignite**
+- **Java 11**
+
+## Результат работы программы
+Запуск:
+```bash
+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
+
+## Вывод
+
+Из полученных результатов можно сделать вывод, что в нашем случае, распределение вычислений между контейенерами привело к значительному замедлению во всех случаях. Накладные расходы на координацию между узлами занимают гораздо большее время, чем сам процесс сортировки.
+
diff --git a/pyzhov_egor_lab_4/src/main/java/MatrixApp.java b/pyzhov_egor_lab_4/src/main/java/MatrixApp.java
new file mode 100644
index 0000000..8798c51
--- /dev/null
+++ b/pyzhov_egor_lab_4/src/main/java/MatrixApp.java
@@ -0,0 +1,156 @@
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.compute.ComputeTaskSplitAdapter;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.cluster.ClusterNode;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Random;
+import java.util.UUID;
+
+public class MatrixApp {
+ 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();
+
+ System.out.println("Original matrix:");
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ matrix[i][j] = r.nextInt(100);
+ System.out.print(matrix[i][j] + "\t");
+ }
+ System.out.println();
+ }
+
+ long start = System.currentTimeMillis();
+ int[][] sortedMatrix = ignite.compute().execute(new MatrixSortingTask(), matrix);
+ long duration = System.currentTimeMillis() - start;
+
+ System.out.println("\nSorted matrix (by first element in descending order):");
+ for (int[] row : sortedMatrix) {
+ for (int value : row) {
+ System.out.print(value + "\t");
+ }
+ System.out.println();
+ }
+
+ System.out.println("Execution time: " + duration + " ms");
+ } catch (IgniteException e) {
+ System.err.println("Ignite Exception: " + e.getMessage());
+ e.printStackTrace();
+ } catch (Exception e) {
+ System.err.println("General Exception: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public static class MatrixSortingTask extends ComputeTaskSplitAdapter {
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ @Override
+ protected List split(int gridSize, int[][] matrix) {
+ List jobs = new ArrayList<>();
+ int batchSize = Math.max(1, matrix.length / gridSize);
+
+ for (int i = 0; i < gridSize; i++) {
+ int start = i * batchSize;
+ int end = (i == gridSize - 1) ? matrix.length : (i + 1) * batchSize;
+
+ if (start < matrix.length) {
+ jobs.add(new MatrixSortingJob(matrix, start, end));
+ System.out.println("[MAIN] Created job for rows " + start + " to " + (end - 1));
+ }
+ }
+
+ return jobs;
+ }
+
+ @Override
+ public int[][] reduce(List results) {
+ List sortedRows = new ArrayList<>();
+
+ for (ComputeJobResult res : results) {
+ int[][] part = res.getData();
+ for (int[] row : part) {
+ sortedRows.add(row);
+ }
+ }
+
+ Collections.sort(sortedRows, (row1, row2) -> Integer.compare(row2[0], row1[0]));
+
+ return sortedRows.toArray(new int[0][]);
+ }
+ }
+
+ public static class MatrixSortingJob implements ComputeJob {
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ private final int[][] matrix;
+ private final int start;
+ private final int end;
+
+ public MatrixSortingJob(int[][] matrix, int start, int end) {
+ this.matrix = matrix;
+ this.start = start;
+ this.end = end;
+ }
+
+ @Override
+ public int[][] execute() {
+ ClusterNode node = ignite.cluster().localNode();
+ UUID nodeId = node.id();
+ String nodeName = "Node-" + nodeId.toString().substring(0, 8);
+
+ System.out.println("[" + nodeName + "] Processing rows " + start + " to " + (end - 1));
+
+ int[][] part = new int[end - start][];
+ System.arraycopy(matrix, start, part, 0, end - start);
+
+ System.out.println("[" + nodeName + "] Part before sorting:");
+ for (int[] row : part) {
+ for (int value : row) {
+ System.out.print(value + "\t");
+ }
+ System.out.println();
+ }
+
+ List rows = new ArrayList<>();
+ for (int[] row : part) {
+ rows.add(row);
+ }
+
+ Collections.sort(rows, (row1, row2) -> Integer.compare(row2[0], row1[0]));
+
+ System.out.println("[" + nodeName + "] Part after sorting:");
+ for (int[] row : rows) {
+ for (int value : row) {
+ System.out.print(value + "\t");
+ }
+ System.out.println();
+ }
+
+ return rows.toArray(new int[0][]);
+ }
+
+ @Override
+ public void cancel() {
+ System.out.println("Job was cancelled");
+ }
+ }
+}
\ No newline at end of file