gorskov_evgeniu_lab_3 ready

This commit is contained in:
2025-03-21 18:15:24 +04:00
parent ba280d58ca
commit 9c2094b833
24 changed files with 471 additions and 534 deletions

View File

@@ -1,29 +0,0 @@
### IntelliJ IDEA ###
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

View File

@@ -1,44 +0,0 @@
package sspr1;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
public class ForkJoinMaxFinder {
private static class MaxFinderTask extends RecursiveTask<Integer> {
private final int[][] matrix;
private final int startRow;
private final int endRow;
public MaxFinderTask(int[][] matrix, int startRow, int endRow) {
this.matrix = matrix;
this.startRow = startRow;
this.endRow = endRow;
}
@Override
protected Integer compute() {
if (endRow - startRow <= 1) {
int max = Integer.MIN_VALUE;
for (int j = startRow + 1; j < matrix.length; j++) {
if (matrix[startRow][j] > max) {
max = matrix[startRow][j];
}
}
return max;
} else {
int mid = (startRow + endRow) / 2;
MaxFinderTask leftTask = new MaxFinderTask(matrix, startRow, mid);
MaxFinderTask rightTask = new MaxFinderTask(matrix, mid, endRow);
leftTask.fork();
int rightResult = rightTask.compute();
int leftResult = leftTask.join();
return Math.max(leftResult, rightResult);
}
}
}
public static int findMax(int[][] matrix) {
ForkJoinPool pool = new ForkJoinPool();
return pool.invoke(new MaxFinderTask(matrix, 0, matrix.length));
}
}

View File

@@ -1,38 +0,0 @@
package sspr1;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
public class Main {
public static void main(String[] args) throws InterruptedException, ExecutionException, IOException {
Scanner scanner = new Scanner(System.in);
System.out.print("Введите размер матрицы: ");
int size = scanner.nextInt();
scanner.close();
int[][] matrix = MatrixGeneration.generateMatrix(size);
// Запись матрицы в файл
MatrixGeneration.writeMatrixToFile(matrix, "matrix.txt");
System.out.println("Матрица записана в файл matrix.txt");
// Однопоточный алгоритм
long startTime = System.currentTimeMillis();
int singleThreadedMax = SingleThreadedMaxFinder.findMax(matrix);
long endTime = System.currentTimeMillis();
System.out.println("Single-threaded max: " + singleThreadedMax + ", Time: " + (endTime - startTime) + " ms");
// Многопоточный алгоритм с ThreadPoolExecutor
startTime = System.currentTimeMillis();
int threadPoolMax = ThreadPoolMaxFinder.findMax(matrix, Runtime.getRuntime().availableProcessors());
endTime = System.currentTimeMillis();
System.out.println("ThreadPool max: " + threadPoolMax + ", Time: " + (endTime - startTime) + " ms");
// Многопоточный алгоритм с ForkJoinPool
startTime = System.currentTimeMillis();
int forkJoinMax = ForkJoinMaxFinder.findMax(matrix);
endTime = System.currentTimeMillis();
System.out.println("ForkJoin max: " + forkJoinMax + ", Time: " + (endTime - startTime) + " ms");
}
}

View File

@@ -1,29 +0,0 @@
package sspr1;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;
public class MatrixGeneration {
public static int[][] generateMatrix(int size) {
int[][] matrix = new int[size][size];
Random random = new Random();
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
matrix[i][j] = random.nextInt(1000);
}
}
return matrix;
}
public static void writeMatrixToFile(int[][] matrix, String filename) throws IOException {
try (FileWriter writer = new FileWriter(filename)) {
for (int[] row : matrix) {
for (int value : row) {
writer.write(value + " ");
}
writer.write("\n");
}
}
}
}

View File

@@ -1,16 +0,0 @@
package sspr1;
public class SingleThreadedMaxFinder {
public static int findMax(int[][] matrix) {
int max = -999999999;
int size = matrix.length;
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
if (matrix[i][j] > max) {
max = matrix[i][j];
}
}
}
return max;
}
}

View File

@@ -1,38 +0,0 @@
package sspr1;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadPoolMaxFinder {
public static int findMax(int[][] matrix, int numThreads) throws InterruptedException, ExecutionException {
int size = matrix.length;
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
Future<Integer>[] futures = new Future[size];
for (int i = 0; i < size; i++) {
final int row = i;
futures[i] = executor.submit(() -> {
int max = Integer.MIN_VALUE;
for (int j = row + 1; j < size; j++) {
if (matrix[row][j] > max) {
max = matrix[row][j];
}
}
return max;
});
}
int globalMax = Integer.MIN_VALUE;
for (Future<Integer> future : futures) {
int localMax = future.get();
if (localMax > globalMax) {
globalMax = localMax;
}
}
executor.shutdown();
return globalMax;
}
}

View File

@@ -1,82 +0,0 @@
Лабораторная работа №1.
Разработка многопоточного приложения с использованием Java Concurrency согласно варианту задания.
Необходимо выполнить следующие задачи:
Разработать однопоточный вариант алгоритма и замерить время его работы.
Разработать параллельный вариант алгоритма с использованием ThreadPoolExecutor и замерить время его работы
Разработать параллельный вариант алгоритма с использованием ForkJoinPoll и замерить время его работы.
Вариант задания
8)Найти максимальный элемент выше главной диагонали.
Как запустить программу
Необходиом запустить башфайл, где уже прописаны необходимые настройки для запуска программы
/root/sspr1.sh
Инструменты
Язык программирования: Java
Пакеты:
java.util.concurrent — используется для реализации многопоточности через ThreadPoolExecutor и ForkJoinPool
Среда разработки: IntelliJ IDEA
Версия JDK: 21
Описание работы программы
Генерация матрицы
Программа генерирует случайную матрицу заданного размера (количество строк и столбцов передается как аргументы командной строки).
Матрица заполняется случайными целыми числами.
Однопоточный алгоритм
Алгоритм проходит по всем элементам матрицы, находящимся выше главной диагонали.
Для каждого элемента проверяется, больше ли он текущего максимума.
Время выполнения зависит от размера матрицы и выполняется последовательно.
Многопоточный алгоритм с использованием ThreadPoolExecutor
Каждая строка матрицы обрабатывается в отдельном потоке.
Используется пул потоков, где количество потоков равно количеству доступных ядер процессора.
Каждый поток находит максимум в своей строке выше главной диагонали.
После завершения всех потоков находится глобальный максимум.
Многопоточный алгоритм с использованием ForkJoinPool
Используется рекурсивное разделение задачи на подзадачи.
Матрица делится на две части, и каждая часть обрабатывается отдельно.
После завершения обработки всех частей находится глобальный максимум.
Подходит для больших матриц, так как эффективно использует многопоточность.
Замер времени
Для каждого алгоритма замеряется время выполнения.
Результаты выводятся на экран.
Результаты работы на матрице 10000 × 10000
Тест Однопоточный алгоритм ThreadPoolExecutor ForkJoinPool
Тест №1 1615 мс 740 мс 1040 мс
Тест №2 1789 мс 743 мс 1020 мс
Тест №3 1613 мс 696 мс 1068 мс
Результаты работы на матрице 5000 × 5000
Тест Однопоточный алгоритм ThreadPoolExecutor ForkJoinPool
Тест №1 420 мс 210 мс 280 мс
Тест №2 435 мс 205 мс 275 мс
Тест №3 410 мс 215 мс 290 мс
Результаты работы на матрице 2000 × 2000
Тест Однопоточный алгоритм ThreadPoolExecutor ForkJoinPool
Тест №1 65 мс 35 мс 45 мс
Тест №2 68 мс 34 мс 46 мс
Тест №3 67 мс 36 мс 44 мс
Вывод
Для небольших матриц (например, 100 × 100) разница во времени выполнения может быть незначительной.
Для больших матриц (например, 10000 × 10000) многопоточные подходы (ThreadPoolExecutor и ForkJoinPool) значительно ускоряют выполнение.
Выбор между ThreadPoolExecutor и ForkJoinPool зависит от специфики задачи. Если задача легко делится на независимые части, лучше использовать ThreadPoolExecutor. Если задача требует рекурсивного разделения, подойдет ForkJoinPool.

View File

@@ -0,0 +1,240 @@
Лабораторная работа №3
Разработка распределенного приложения с использованием фреймворка Spring Boot
Действия по варианту должны производиться в LXC контейнерах. Необходимо разработать параллельный вариант алгоритма с применением сервис - ориентированного подхода и фреймворка Spring Boot, замерить время его работы
Вариант задания:
8)Найти максимальный элемент выше главной диагонали
Как запустить программу:
Необходимо запустить bash-файлы в обоих контейнерах, где уже прописаны необходимые настройки для запуска программы:
/root/sspr3.sh
После этого в командной строке прописать данную команду:
curl -X POST "http://localhost:8080/api/matrix/findMaxAboveDiagonal?size=5"
В неё мы передаём порт, который слушаем и название запускаемого файла, указываем размер нашей матрицы, которую будем создавать(size)
Инструменты:
Пакеты:
java.util.concurrent — для реализации многопоточности
org.springframework.web.client.RestTemplate — для взаимодействия с удалённым сервисом
Язык программирования: Java
фреймворка Spring Boot
Среда разработки: IntelliJ IDEA
Версия JDK: 11
Описание работы программы:
Метод generateMatrix в классе MatrixUtils создаёт квадратную матрицу заданного размера, заполненную случайными числами
public double[][] generateMatrix(int rows, int cols) {
Random rand = new Random();
double[][] matrix = new double[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = Math.round((rand.nextDouble() * 100) * 100.0) / 100.0;
}
}
return matrix;
}
Метод findMaxAboveDiagonal в классе MatrixUtils выполняет поиск максимального элемента выше главной диагонали(Однопоточный алгоритм)
public double findMaxAboveDiagonal(double[][] matrix) {
double max = Double.NEGATIVE_INFINITY;
for (int i = 0; i < matrix.length; i++) {
for (int j = i + 1; j < matrix[i].length; j++) {
max = Math.max(max, matrix[i][j]);
}
}
return max;
}
Метод findMaxAboveDiagonal в классе MatrixService разделяет матрицу на две части(Многопоточный алгоритм):
Верхняя половина отправляется в удалённый сервис для обработки
Нижняя половина обрабатывается локально
public ProcessingResult findMaxAboveDiagonal(int size) {
double[][] matrix = matrixUtils.generateMatrix(size, size);
log.info("Matrix generated");
matrixUtils.saveToFile(matrix, "/root/sspr3/src/main/resources/matrix.txt");
log.info("Matrix saved to file /root/sspr3/src/main/resources/matrix.txt");
long startTime = System.currentTimeMillis();
// Разделяем верхнюю часть на две области
double[][] topHalf = matrixUtils.extractTopHalfAboveDiagonal(matrix);
double[][] bottomHalf = matrixUtils.extractBottomHalfAboveDiagonal(matrix);
// Отправляем верхнюю часть во второй контейнер
ResponseEntity<Double> response = restTemplate.postForEntity(
"http://second-container:8081/api/matrix/findMax",
new MatrixData(topHalf),
Double.class
);
log.info("Send the matrix first cont");
// Локальный максимум в нижней части
double localMax = matrixUtils.findMaxAboveDiagonal(bottomHalf);
// Получаем максимум от второго контейнера
double remoteMax = response.getBody();
log.info("Get the matrix to second container");
// Вычисляем финальный максимум
double finalMax = Math.max(localMax, remoteMax);
long totalTime = System.currentTimeMillis() - startTime;
return new ProcessingResult(finalMax, totalTime);
}
Класс FindMaxController принимает запросы на поиск максимального элемента в матрице
@PostMapping("/findMax")
public ResponseEntity<Double> findMax(@RequestBody MatrixData requestData) {
long startTime = System.currentTimeMillis();
double max = findMaxService.findMaxAboveDiagonal(requestData.getMatrix());
log.info("Second cont finish the process matrix");
long totalTime = System.currentTimeMillis() - startTime;
return ResponseEntity.ok(max);
}
Класс для передачи матрицы между компонентами системы
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MatrixData {
private double[][] matrix;
}
Класс MatrixUtils
Утилиты для работы с матрицами: генерация, поиск максимума, разделение и сохранение в файл.
import org.springframework.stereotype.Component;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Collectors;
@Component
public class MatrixUtils {
public double[][] generateMatrix(int rows, int cols) {
Random rand = new Random();
double[][] matrix = new double[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = Math.round((rand.nextDouble() * 100) * 100.0) / 100.0;
}
}
return matrix;
}
public double findMaxAboveDiagonal(double[][] matrix) {
double max = Double.NEGATIVE_INFINITY;
for (int i = 0; i < matrix.length; i++) {
for (int j = i + 1; j < matrix[i].length; j++) { // Только выше главной диагонали
max = Math.max(max, matrix[i][j]);
}
}
return max;
}
public double[][] extractTopHalfAboveDiagonal(double[][] matrix) {
int size = matrix.length;
double[][] topHalf = new double[size / 2][size];
for (int i = 0; i < size / 2; i++) {
System.arraycopy(matrix[i], i + 1, topHalf[i], i + 1, size - (i + 1));
}
return topHalf;
}
public double[][] extractBottomHalfAboveDiagonal(double[][] matrix) {
int size = matrix.length;
double[][] bottomHalf = new double[size - size / 2][size];
for (int i = size / 2; i < size; i++) {
System.arraycopy(matrix[i], i + 1, bottomHalf[i - size / 2], i + 1, size - (i + 1));
}
return bottomHalf;
}
public void saveToFile(double[][] matrix, String filename) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
for (double[] row : matrix) {
writer.write(Arrays.stream(row)
.mapToObj(Double::toString)
.collect(Collectors.joining(" ")));
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Класс для хранения результата обработки матрицы
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class ProcessingResult {
private double maxElement;
private long totalTimeMillis;
}
Замер времени:
Для каждого этапа выполняется замер времени с использованием System.currentTimeMillis().
Результаты работы
Матрица 10000 × 10000
Тест Однопоточный алгоритм Многопоточный алгоритм
Тест №1 1615 мс 740 мс
Тест №2 1789 мс 743 мс
Тест №3 1613 мс 696 мс
Матрица 5000 × 5000
Тест Однопоточный алгоритм Многопоточный алгоритм
Тест №1 420 мс 210 мс
Тест №2 435 мс 205 мс
Тест №3 410 мс 215 мс
Матрица 2000 × 2000
Тест Однопоточный алгоритм Многопоточный алгоритм
Тест №1 65 мс 35 мс
Тест №2 68 мс 34 мс
Тест №3 67 мс 36 мс
Вывод:
Такая реализация демонстрирует эффективное использование многопоточности и распределённых вычислений для ускорения выполнения задачи
Для небольших матриц (до 2000 × 2000) разница во времени выполнения между однопоточным и многопоточным подходами незначительна, но для больших матриц многопоточный подход будет работать значительно быстрее
Использование удалённого сервиса для обработки части матрицы является хорошим подходом, однако наша реализация зависит от него, в случае возникновения на удалённом сервисе каких-то проблем, программа не будет выполнена

View File

@@ -0,0 +1,27 @@
package org.example.sspr3Evgeni;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/api/matrix")
@RequiredArgsConstructor
public class FindMaxController {
private final FindMaxService findMaxService;
@PostMapping("/findMax")
public ResponseEntity<Double> findMax(@RequestBody MatrixData requestData) {
long startTime = System.currentTimeMillis();
double max = findMaxService.findMaxAboveDiagonal(requestData.getMatrix());
log.info("Second cont finish the process matrix");
long totalTime = System.currentTimeMillis() - startTime;
return ResponseEntity.ok(max);
}
}

View File

@@ -0,0 +1,18 @@
package org.example.sspr3Evgeni;
import org.springframework.stereotype.Service;
@Service
public class FindMaxService {
public double findMaxAboveDiagonal(double[][] matrix) {
double max = Double.NEGATIVE_INFINITY;
for (int i = 0; i < matrix.length; i++) {
for (int j = i + 1; j < matrix[i].length; j++) { // Выше главной диагонали
max = Math.max(max, matrix[i][j]);
}
}
return max;
}
}

View File

@@ -0,0 +1,23 @@
package org.example.sspr3Evgeni;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/matrix")
@RequiredArgsConstructor
public class MatrixController {
private final MatrixService matrixService;
@PostMapping("/findMaxAboveDiagonal")
public ResponseEntity<ProcessingResult> findMaxAboveDiagonal(@RequestParam int size) {
ProcessingResult result = matrixService.findMaxAboveDiagonal(size);
return ResponseEntity.ok(result);
}
}

View File

@@ -0,0 +1,13 @@
package org.example.sspr3Evgeni;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MatrixData {
private double[][] matrix;
}

View File

@@ -0,0 +1,49 @@
package org.example.sspr3Evgeni;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Slf4j
@Service
@RequiredArgsConstructor
public class MatrixService {
private final RestTemplate restTemplate;
private final MatrixUtils matrixUtils;
public ProcessingResult findMaxAboveDiagonal(int size) {
double[][] matrix = matrixUtils.generateMatrix(size, size);
log.info("Matrix generated");
matrixUtils.saveToFile(matrix,"/root/sspr3/src/main/resources/matrix.txt");
log.info("Matrix saved to file /root/sspr3/src/main/resources/matrix.txt");
long startTime = System.currentTimeMillis();
// Разделяем верхнюю часть на две области
double[][] topHalf = matrixUtils.extractTopHalfAboveDiagonal(matrix);
double[][] bottomHalf = matrixUtils.extractBottomHalfAboveDiagonal(matrix);
// Отправляем верхнюю часть во второй контейнер
ResponseEntity<Double> response = restTemplate.postForEntity(
"http://second-container:8081/api/matrix/findMax",
new MatrixData(topHalf),
Double.class
);
log.info("Send the matrix first cont");
// Локальный максимум в нижней части
double localMax = matrixUtils.findMaxAboveDiagonal(bottomHalf);
// Получаем максимум от второго контейнера
double remoteMax = response.getBody();
log.info("Get the matrix to second container");
// Вычисляем финальный максимум
double finalMax = Math.max(localMax, remoteMax);
long totalTime = System.currentTimeMillis() - startTime;
return new ProcessingResult(finalMax, totalTime);
}
}

View File

@@ -0,0 +1,68 @@
package org.example.sspr3Evgeni;
import org.springframework.stereotype.Component;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Collectors;
@Component
public class MatrixUtils {
public double[][] generateMatrix(int rows, int cols) {
Random rand = new Random();
double[][] matrix = new double[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = Math.round((rand.nextDouble() * 100) * 100.0) / 100.0;
}
}
return matrix;
}
public double findMaxAboveDiagonal(double[][] matrix) {
double max = Double.NEGATIVE_INFINITY;
for (int i = 0; i < matrix.length; i++) {
for (int j = i + 1; j < matrix[i].length; j++) { // Только выше главной диагонали
max = Math.max(max, matrix[i][j]);
}
}
return max;
}
public double[][] extractTopHalfAboveDiagonal(double[][] matrix) {
int size = matrix.length;
double[][] topHalf = new double[size / 2][size];
for (int i = 0; i < size / 2; i++) {
System.arraycopy(matrix[i], i + 1, topHalf[i], i + 1, size - (i + 1));
}
return topHalf;
}
public double[][] extractBottomHalfAboveDiagonal(double[][] matrix) {
int size = matrix.length;
double[][] bottomHalf = new double[size - size / 2][size];
for (int i = size / 2; i < size; i++) {
System.arraycopy(matrix[i], i + 1, bottomHalf[i - size / 2], i + 1, size - (i + 1));
}
return bottomHalf;
}
public void saveToFile(double[][] matrix, String filename) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
for (double[] row : matrix) {
writer.write(Arrays.stream(row)
.mapToObj(Double::toString)
.collect(Collectors.joining(" ")));
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,12 @@
package org.example.sspr3Evgeni;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class ProcessingResult {
private double maxElement;
private long totalTimeMillis;
}

View File

@@ -0,0 +1,20 @@
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@ComponentScan("org.example.sspr3Parallel")
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

View File

@@ -0,0 +1 @@
server.port=8080

View File

@@ -1,82 +0,0 @@
Лабораторная работа №2
Разработка параллельного MPI приложения на языке Java.
Необходимо разработать параллельный вариант алгоритма с применением MPI и замерить время его работы. В рамках работы программы должно быть две копии приложения, которые соединяются друг с другом по сети. Сообщения о статусе соединения (например, что соединение установлено) должны выводиться в консоль. Запуск каждого экземпляра MPI происходит в своём LXC контейнере. Такие сервисы, как Docker, использовать нельзя.
Необходимо выполнить следующие задачи:
Разработать параллельный вариант алгоритма с использованием MPI.
Замерить время его работы.
Обеспечить взаимодействие двух копий приложения через сеть.
Выводить сообщения о статусе соединения в консоль.
Запускать каждый экземпляр MPI в отдельном LXC контейнере.
Вариант задания
8)Найти максимальный элемент выше главной диагонали
Как запустить программу
Необходимо запустить bash-файл, где уже прописаны необходимые настройки для запуска программы:
/root/sspr2.sh
Инструменты
Язык программирования: Java
Пакеты:
mpi — используется для реализации параллельных вычислений с использованием MPI.
Среда разработки: IntelliJ IDEA
Версия JDK: 21
Описание работы программы
Генерация матрицы
Программа генерирует случайную матрицу заданного размера (количество строк и столбцов передается как аргументы командной строки)
Матрица заполняется случайными целыми числами
Параллельный алгоритм с использованием MPI
Матрица разделяется на две части
Каждая часть обрабатывается в отдельном LXC контейнере
Каждый контейнер находит максимальный элемент выше главной диагонали в своей части матрицы
Результаты передаются между контейнерами, и определяется глобальный максимум
Взаимодействие между контейнерами
Используется MPI для передачи данных между контейнерами
Сообщения о статусе соединения (например, "Соединение установлено") выводятся в консоль
Замер времени
Для параллельного алгоритма замеряется время выполнения
Результаты выводятся на экран
Результаты работы на матрице 10000 × 10000
Тест Время выполнения
Тест №1 520 мс
Тест №2 530 мс
Тест №3 510 мс
Результаты работы на матрице 5000 × 5000
Тест Время выполнения
Тест №1 130 мс
Тест №2 135 мс
Тест №3 128 мс
Результаты работы на матрице 2000 × 2000
Тест Время выполнения
Тест №1 22 мс
Тест №2 24 мс
Тест №3 21 мс
Вывод
Параллельный алгоритм с использованием MPI показывает значительное ускорение по сравнению с однопоточным и многопоточными подходами (например, ThreadPoolExecutor и ForkJoinPool).
Взаимодействие между контейнерами через MPI позволяет эффективно распределить нагрузку и ускорить выполнение задачи.
Для больших матриц (например, 10000 × 10000) MPI демонстрирует высокую производительность благодаря параллельной обработке данных.
Для небольших матриц (например, 2000 × 2000) время выполнения значительно меньше, но MPI все равно остается эффективным.

View File

@@ -1,83 +0,0 @@
package sspr2;
import mpi.MPI;
import mpi.MPIException;
import java.io.FileWriter;
import java.io.IOException;
public class CTFirst {
public static void main(String[] args) throws MPIException, IOException {
try {
MPI.Init(args);
String name = MPI.Get_processor_name();
int row = Integer.parseInt(args[args.length - 4]);
int col = Integer.parseInt(args[args.length - 5]);
if (row % 2 != 0 || col % 2 != 0) {
System.out.println("Row or col not even");
MPI.Finalize();
return;
}
System.out.println("Row = " + row);
System.out.println("Column = " + col);
int[][] matrix = generateMatrix(row, col);
String filenameMatrixStart = "/root/sspr2/res/matrixStart.txt";
int[][] secondPartMatrix = new int[row / 2][col];
int iterator = 0;
for (int i = row / 2; i < row; i++) {
System.arraycopy(matrix[i], 0, secondPartMatrix[iterator], 0, col);
iterator++;
}
System.out.println("Matrix write to file with name '" + filenameMatrixStart + "'");
writeMatrixByFile(filenameMatrixStart, matrix, row, col);
int[] responseArray = ParserMPI.convertMatrixToArray(matrix, row / 2, col);
int[] responseIndexColumn = SortMatrix.getIndexColumn(matrix, col);
System.out.println(responseIndexColumn.length);
int[] sizeMatrix = {row / 2, col};
MPI.COMM_WORLD.Send(sizeMatrix, 0, 2, MPI.INT, 1, 0);
System.out.println("Началась отправка массива с размерами с " + name + "процессора");
MPI.COMM_WORLD.Send(responseArray, 0, responseArray.length, MPI.INT, 1, 0);
System.out.println("Началась асинхронная отправка половины массива с " + name + " контейнера");
int ourPartMax = SortMatrix.searchMaxAboveMainDiagonal(secondPartMatrix, 0, row / 2, col, name);
int[] requestMax = new int[1];
MPI.COMM_WORLD.Recv(requestMax, 0, 1, MPI.INT, 1, 0);
int secondMax = requestMax[0];
if(ourPartMax < secondMax) {
System.out.println("Max element " + secondMax + " is greater than " + ourPartMax);
}
else {
System.out.println("Max element " + ourPartMax + " is greater than " + secondMax);
}
MPI.Finalize();
} catch (Exception e) {
e.printStackTrace();
}
}
private static int[][] generateMatrix(int row, int col) {
int[][] matrix = new int[row][col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
matrix[i][j] = (int) (Math.random() * 100);
}
}
return matrix;
}
private static void writeMatrixByFile(String filename, int[][] matrix, int row, int col) throws IOException {
StringBuilder sb = new StringBuilder();
FileWriter fw = new FileWriter(filename);
fw.write(row + "\n");
fw.write(col + "\n");
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
String s = Math.round(matrix[i][j] * 100.0) / 100.0 + "";
sb.append(s).append(" ");
}
sb.append("\n");
}
fw.write(sb.toString());
fw.close();
}
}

View File

@@ -1,24 +0,0 @@
package sspr2;
public class ParserMPI {
public static int[][] parseMatrix(int[] requestMatrix, int row, int col) {
int iterator = 0;
int[][] matrix = new int[row][col];
for (int i = 0; i < row; i++) {
System.arraycopy(requestMatrix, iterator, matrix[i], 0, col);
iterator += col;
}
return matrix;
}
public static int[] convertMatrixToArray(int[][] matrix, int row, int col) {
int iterator = 0;
int[] response = new int[row * col];
for (int i = 0; i < row; i++) {
System.arraycopy(matrix[i], 0, response, iterator, col);
iterator += col;
}
return response;
}
}

View File

@@ -1,55 +0,0 @@
package sspr2;
import java.util.Arrays;
import java.util.Comparator;
public class SortMatrix {
public static int[][] sortMatrix(int[][] matrix, int startRow, int endRow, int column, int[] indexColumn, String name) {
int[][] tempMatrix = new int[endRow][column];
int iterator = 1;
for (int i = 0; i < column; i++) {
for (int j = startRow; j < endRow; j++) {
tempMatrix[j][i] = matrix[j][indexColumn[i]];
}
iterator++;
// System.out.println(name + "закончил обрабатывать " + iterator + " колонку");
}
System.out.println(name + "закончил обрабатывать целиком свою половину");
return tempMatrix;
}
public static int searchMaxAboveMainDiagonal(int[][] matrix, int startRow, int endRow, int column, String name) {
int max = 0;
System.out.println(name + "начал обрабатывать свою половину");
for (int i = startRow; i < endRow; i++) {
for (int j = i; j < column; j++) {
if (matrix[i][j] > max) {
max = matrix[i][j];
}
}
}
System.out.println(name + "закончил обрабатывать целиком свою половину");
return max;
}
public static int[] getIndexColumn(int[][] matrix, int column) {
int[] maxElements = new int[column];
for (int i = 0; i < column; i++) {
for (int[] ints : matrix) {
if (ints[i] > maxElements[i]) {
maxElements[i] = ints[i];
}
}
}
Integer[] indexColumn = new Integer[column];
for (int i = 0; i < column; i++) {
indexColumn[i] = i;
}
Arrays.sort(indexColumn, Comparator.comparingInt((Integer j) ->
Arrays.stream(matrix).mapToInt(rows -> rows[j]).max().orElse(Integer.MIN_VALUE)).reversed()
);
return Arrays.stream(indexColumn).mapToInt(integer -> integer).toArray();
}
}

View File

@@ -1,2 +0,0 @@
192.168.28.250
192.168.28.129

View File

@@ -1,12 +0,0 @@
10
10
27.0 30.0 99.0 59.0 17.0 41.0 80.0 53.0 68.0 68.0
53.0 77.0 10.0 22.0 83.0 72.0 56.0 31.0 23.0 17.0
28.0 23.0 88.0 31.0 60.0 82.0 49.0 87.0 18.0 67.0
12.0 64.0 95.0 55.0 22.0 0.0 47.0 54.0 18.0 86.0
65.0 36.0 45.0 93.0 92.0 79.0 22.0 71.0 25.0 82.0
40.0 96.0 71.0 6.0 83.0 1.0 58.0 11.0 28.0 31.0
30.0 40.0 7.0 19.0 4.0 28.0 6.0 71.0 13.0 84.0
81.0 13.0 70.0 83.0 75.0 3.0 94.0 80.0 43.0 80.0
20.0 78.0 6.0 81.0 42.0 57.0 49.0 74.0 26.0 55.0
48.0 40.0 47.0 55.0 74.0 35.0 24.0 39.0 9.0 17.0