pyzhov_egor_lab_4 is ready #149

Merged
sevastyan_b merged 3 commits from :pyzhov_egor_lab_4 into main 2025-05-03 15:12:13 +04:00
6 changed files with 472 additions and 0 deletions

40
pyzhov_egor_lab_4/.gitignore vendored Normal file
View File

@@ -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

View File

@@ -0,0 +1,20 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="igniteInstanceName" value="my-cluster"/>
<property name="peerClassLoadingEnabled" value="true"/>
<property name="cacheConfiguration">
<list>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="myCache"/>
<property name="backups" value="1"/>
<property name="cacheMode" value="PARTITIONED"/>
</bean>
</list>
</property>
</bean>
</beans>

View File

@@ -0,0 +1,35 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="igniteInstanceName" value="my-cluster"/>
<property name="peerClassLoadingEnabled" value="true"/>
<property name="discoverySpi">
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
<property name="ipFinder">
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
<property name="addresses">
<list>
<value>192.168.17.117:47500</value>
<value>192.168.17.118:47500</value>
</list>
</property>
</bean>
</property>
</bean>
</property>
<property name="cacheConfiguration">
<list>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="myCache"/>
<property name="backups" value="1"/>
<property name="cacheMode" value="PARTITIONED"/>
</bean>
</list>
</property>
</bean>
</beans>

50
pyzhov_egor_lab_4/pom.xml Normal file
View File

@@ -0,0 +1,50 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.urlshort</groupId>
<artifactId>sspr4</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>lab4</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-core</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-indexing</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-spring</artifactId>
<version>2.17.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.18</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

171
pyzhov_egor_lab_4/readme.md Normal file
View File

@@ -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<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) для обработки каждой части.
```java
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]));
```
Класс подзадачи, который получает часть для обработки, сортирует и возвращает отсортированную часть.
```java
@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][]);
}
```
Метод получающий результаты со всех узлов, выполняет финальную сортировку объединенной матрицы.
## Запуск приложения
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
## Вывод
Из полученных результатов можно сделать вывод, что в нашем случае, распределение вычислений между контейенерами привело к значительному замедлению во всех случаях. Накладные расходы на координацию между узлами занимают гораздо большее время, чем сам процесс сортировки.

View File

@@ -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<int[][], int[][]> {
@IgniteInstanceResource
private Ignite ignite;
@Override
protected List<ComputeJob> split(int gridSize, int[][] matrix) {
List<ComputeJob> 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<ComputeJobResult> results) {
List<int[]> 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<int[]> 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");
}
}
}