init
This commit is contained in:
59
main/pom.xml
Normal file
59
main/pom.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>matrix-main-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>matrix-main-service</name>
|
||||
<description>Main service for distributed matrix minimum search</description>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.example.matrix;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class MatrixMainApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MatrixMainApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.example.matrix.client;
|
||||
|
||||
import com.example.matrix.model.Matrix;
|
||||
import com.example.matrix.model.MinResult;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Service
|
||||
public class WorkerServiceClient {
|
||||
|
||||
private final WebClient webClient;
|
||||
|
||||
public WorkerServiceClient(@Value("${worker.service.url}") String workerServiceUrl) {
|
||||
this.webClient = WebClient.builder()
|
||||
.baseUrl(workerServiceUrl)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Mono<MinResult> findMinimum(Matrix matrix) {
|
||||
return webClient.post()
|
||||
.uri("/matrix/min")
|
||||
.bodyValue(matrix)
|
||||
.retrieve()
|
||||
.bodyToMono(MinResult.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.example.matrix.controller;
|
||||
|
||||
import com.example.matrix.model.Matrix;
|
||||
import com.example.matrix.model.MinResult;
|
||||
import com.example.matrix.service.MatrixService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/matrix")
|
||||
@RequiredArgsConstructor
|
||||
public class MatrixController {
|
||||
|
||||
private final MatrixService matrixService;
|
||||
|
||||
@PostMapping("/generate")
|
||||
public Matrix generateMatrix(@RequestParam int rows, @RequestParam int cols) {
|
||||
return matrixService.generateMatrix(rows, cols);
|
||||
}
|
||||
|
||||
@PostMapping("/min/sequential")
|
||||
public MinResult findMinimumSequential(@RequestBody Matrix matrix) {
|
||||
return matrixService.findMinimumSequential(matrix);
|
||||
}
|
||||
|
||||
@PostMapping("/min/parallel")
|
||||
public MinResult findMinimumParallel(@RequestBody Matrix matrix) throws ExecutionException, InterruptedException {
|
||||
return matrixService.findMinimumParallel(matrix);
|
||||
}
|
||||
|
||||
// Простой эндпоинт для замера времени выполнения
|
||||
@PostMapping("/benchmark")
|
||||
public String benchmark(@RequestParam int rows, @RequestParam int cols, @RequestParam int iterations) throws ExecutionException, InterruptedException {
|
||||
Matrix matrix = matrixService.generateMatrix(rows, cols);
|
||||
|
||||
long totalSequentialTime = 0;
|
||||
long totalParallelTime = 0;
|
||||
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
MinResult sequentialResult = matrixService.findMinimumSequential(matrix);
|
||||
MinResult parallelResult = matrixService.findMinimumParallel(matrix);
|
||||
|
||||
totalSequentialTime += sequentialResult.getProcessingTimeMs();
|
||||
totalParallelTime += parallelResult.getProcessingTimeMs();
|
||||
|
||||
// Проверка корректности результатов
|
||||
if (sequentialResult.getMinValue() != parallelResult.getMinValue()) {
|
||||
return "Error: different minimum values found. Sequential: " +
|
||||
sequentialResult.getMinValue() + ", Parallel: " + parallelResult.getMinValue();
|
||||
}
|
||||
}
|
||||
|
||||
double avgSequentialTime = (double) totalSequentialTime / iterations;
|
||||
double avgParallelTime = (double) totalParallelTime / iterations;
|
||||
double speedup = avgSequentialTime / avgParallelTime;
|
||||
|
||||
return String.format("Benchmark results (average over %d iterations):\n" +
|
||||
"Matrix size: %dx%d\n" +
|
||||
"Sequential execution time: %.2f ms\n" +
|
||||
"Parallel execution time: %.2f ms\n" +
|
||||
"Speedup: %.2fx",
|
||||
iterations, rows, cols, avgSequentialTime, avgParallelTime, speedup);
|
||||
}
|
||||
}
|
||||
45
main/src/main/java/com/example/matrix/model/Matrix.java
Normal file
45
main/src/main/java/com/example/matrix/model/Matrix.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package com.example.matrix.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Matrix {
|
||||
private int[][] data;
|
||||
private int rows;
|
||||
private int cols;
|
||||
|
||||
public Matrix(int rows, int cols) {
|
||||
this.rows = rows;
|
||||
this.cols = cols;
|
||||
this.data = new int[rows][cols];
|
||||
}
|
||||
|
||||
// Метод для заполнения матрицы случайными значениями
|
||||
public void fillRandom(int min, int max) {
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cols; j++) {
|
||||
data[i][j] = min + (int) (Math.random() * (max - min + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Получение подматрицы (части матрицы)
|
||||
public Matrix getSubMatrix(int startRow, int endRow) {
|
||||
if (startRow < 0 || endRow > rows || startRow >= endRow) {
|
||||
throw new IllegalArgumentException("Invalid row range");
|
||||
}
|
||||
|
||||
int subRows = endRow - startRow;
|
||||
Matrix subMatrix = new Matrix(subRows, cols);
|
||||
|
||||
for (int i = 0; i < subRows; i++) {
|
||||
System.arraycopy(data[startRow + i], 0, subMatrix.data[i], 0, cols);
|
||||
}
|
||||
|
||||
return subMatrix;
|
||||
}
|
||||
}
|
||||
22
main/src/main/java/com/example/matrix/model/MinResult.java
Normal file
22
main/src/main/java/com/example/matrix/model/MinResult.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.example.matrix.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MinResult {
|
||||
private int minValue;
|
||||
private int row;
|
||||
private int col;
|
||||
private long processingTimeMs;
|
||||
|
||||
public MinResult(int minValue) {
|
||||
this.minValue = minValue;
|
||||
this.row = -1;
|
||||
this.col = -1;
|
||||
this.processingTimeMs = 0;
|
||||
}
|
||||
}
|
||||
104
main/src/main/java/com/example/matrix/service/MatrixService.java
Normal file
104
main/src/main/java/com/example/matrix/service/MatrixService.java
Normal file
@@ -0,0 +1,104 @@
|
||||
package com.example.matrix.service;
|
||||
|
||||
import com.example.matrix.client.WorkerServiceClient;
|
||||
import com.example.matrix.model.Matrix;
|
||||
import com.example.matrix.model.MinResult;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MatrixService {
|
||||
|
||||
private final WorkerServiceClient workerServiceClient;
|
||||
|
||||
// Метод для генерации матрицы заданного размера
|
||||
public Matrix generateMatrix(int rows, int cols) {
|
||||
Matrix matrix = new Matrix(rows, cols);
|
||||
matrix.fillRandom(-100, 100); // Заполняем случайными значениями от -100 до 100
|
||||
return matrix;
|
||||
}
|
||||
|
||||
// Поиск минимального элемента в матрице (последовательный алгоритм для сравнения)
|
||||
public MinResult findMinimumSequential(Matrix matrix) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
int minValue = Integer.MAX_VALUE;
|
||||
int minRow = -1;
|
||||
int minCol = -1;
|
||||
|
||||
for (int i = 0; i < matrix.getRows(); i++) {
|
||||
for (int j = 0; j < matrix.getCols(); j++) {
|
||||
if (matrix.getData()[i][j] < minValue) {
|
||||
minValue = matrix.getData()[i][j];
|
||||
minRow = i;
|
||||
minCol = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long processingTime = System.currentTimeMillis() - startTime;
|
||||
return new MinResult(minValue, minRow, minCol, processingTime);
|
||||
}
|
||||
|
||||
// Параллельный поиск минимума с использованием двух сервисов
|
||||
public MinResult findMinimumParallel(Matrix matrix) throws ExecutionException, InterruptedException {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// Разделяем матрицу на две части
|
||||
int halfRows = matrix.getRows() / 2;
|
||||
Matrix firstHalf = matrix.getSubMatrix(0, halfRows);
|
||||
Matrix secondHalf = matrix.getSubMatrix(halfRows, matrix.getRows());
|
||||
|
||||
// Находим минимум в первой половине локально
|
||||
CompletableFuture<MinResult> localFuture = CompletableFuture.supplyAsync(() -> {
|
||||
int minValue = Integer.MAX_VALUE;
|
||||
int minRow = -1;
|
||||
int minCol = -1;
|
||||
|
||||
for (int i = 0; i < firstHalf.getRows(); i++) {
|
||||
for (int j = 0; j < firstHalf.getCols(); j++) {
|
||||
if (firstHalf.getData()[i][j] < minValue) {
|
||||
minValue = firstHalf.getData()[i][j];
|
||||
minRow = i;
|
||||
minCol = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new MinResult(minValue, minRow, minCol, 0);
|
||||
});
|
||||
|
||||
// Находим минимум во второй половине через Worker Service
|
||||
CompletableFuture<MinResult> remoteFuture = workerServiceClient.findMinimum(secondHalf)
|
||||
.map(result -> {
|
||||
// Корректируем индекс строки (добавляем смещение)
|
||||
if (result.getRow() >= 0) {
|
||||
result.setRow(result.getRow() + halfRows);
|
||||
}
|
||||
return result;
|
||||
})
|
||||
.toFuture();
|
||||
|
||||
// Ждем завершения обоих вычислений и выбираем минимальный результат
|
||||
CompletableFuture<MinResult> combinedFuture = localFuture.thenCombine(remoteFuture, (local, remote) -> {
|
||||
if (local.getMinValue() <= remote.getMinValue()) {
|
||||
return local;
|
||||
} else {
|
||||
return remote;
|
||||
}
|
||||
});
|
||||
|
||||
MinResult result = combinedFuture.get();
|
||||
long processingTime = System.currentTimeMillis() - startTime;
|
||||
result.setProcessingTimeMs(processingTime);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
2
main/src/main/resources/application.properties
Normal file
2
main/src/main/resources/application.properties
Normal file
@@ -0,0 +1,2 @@
|
||||
server.port=8080
|
||||
worker.service.url=http://worker-vm:8081
|
||||
55
worker/pom.xml
Normal file
55
worker/pom.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>matrix-worker-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>matrix-worker-service</name>
|
||||
<description>Worker service for distributed matrix minimum search</description>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.example.matrix;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class MatrixWorkerApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MatrixWorkerApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.example.matrix.controller;
|
||||
|
||||
import com.example.matrix.model.Matrix;
|
||||
import com.example.matrix.model.MinResult;
|
||||
import com.example.matrix.service.WorkerService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
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;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/matrix")
|
||||
@RequiredArgsConstructor
|
||||
public class WorkerController {
|
||||
|
||||
private final WorkerService workerService;
|
||||
|
||||
@PostMapping("/min")
|
||||
public MinResult findMinimum(@RequestBody Matrix matrix) {
|
||||
return workerService.findMinimum(matrix);
|
||||
}
|
||||
}
|
||||
45
worker/src/main/java/com/example/matrix/model/Matrix.java
Normal file
45
worker/src/main/java/com/example/matrix/model/Matrix.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package com.example.matrix.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Matrix {
|
||||
private int[][] data;
|
||||
private int rows;
|
||||
private int cols;
|
||||
|
||||
public Matrix(int rows, int cols) {
|
||||
this.rows = rows;
|
||||
this.cols = cols;
|
||||
this.data = new int[rows][cols];
|
||||
}
|
||||
|
||||
// Метод для заполнения матрицы случайными значениями
|
||||
public void fillRandom(int min, int max) {
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cols; j++) {
|
||||
data[i][j] = min + (int) (Math.random() * (max - min + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Получение подматрицы (части матрицы)
|
||||
public Matrix getSubMatrix(int startRow, int endRow) {
|
||||
if (startRow < 0 || endRow > rows || startRow >= endRow) {
|
||||
throw new IllegalArgumentException("Invalid row range");
|
||||
}
|
||||
|
||||
int subRows = endRow - startRow;
|
||||
Matrix subMatrix = new Matrix(subRows, cols);
|
||||
|
||||
for (int i = 0; i < subRows; i++) {
|
||||
System.arraycopy(data[startRow + i], 0, subMatrix.data[i], 0, cols);
|
||||
}
|
||||
|
||||
return subMatrix;
|
||||
}
|
||||
}
|
||||
22
worker/src/main/java/com/example/matrix/model/MinResult.java
Normal file
22
worker/src/main/java/com/example/matrix/model/MinResult.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.example.matrix.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MinResult {
|
||||
private int minValue;
|
||||
private int row;
|
||||
private int col;
|
||||
private long processingTimeMs;
|
||||
|
||||
public MinResult(int minValue) {
|
||||
this.minValue = minValue;
|
||||
this.row = -1;
|
||||
this.col = -1;
|
||||
this.processingTimeMs = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.example.matrix.service;
|
||||
|
||||
import com.example.matrix.model.Matrix;
|
||||
import com.example.matrix.model.MinResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class WorkerService {
|
||||
|
||||
public MinResult findMinimum(Matrix matrix) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
int minValue = Integer.MAX_VALUE;
|
||||
int minRow = -1;
|
||||
int minCol = -1;
|
||||
|
||||
for (int i = 0; i < matrix.getRows(); i++) {
|
||||
for (int j = 0; j < matrix.getCols(); j++) {
|
||||
if (matrix.getData()[i][j] < minValue) {
|
||||
minValue = matrix.getData()[i][j];
|
||||
minRow = i;
|
||||
minCol = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long processingTime = System.currentTimeMillis() - startTime;
|
||||
return new MinResult(minValue, minRow, minCol, processingTime);
|
||||
}
|
||||
}
|
||||
1
worker/src/main/resources/application.properties
Normal file
1
worker/src/main/resources/application.properties
Normal file
@@ -0,0 +1 @@
|
||||
server.port=8081
|
||||
Reference in New Issue
Block a user