Merge pull request 'putincev_daniil_lab_5' (#393) from putincev_daniil_lab_5 into main

Reviewed-on: #393
This commit was merged in pull request #393.
This commit is contained in:
2025-12-08 23:01:41 +04:00
3 changed files with 170 additions and 0 deletions

View File

@@ -0,0 +1,121 @@
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MatrixMultiplier {
public static double[][] multiply(double[][] a, double[][] b, int numThreads) {
int n = a.length;
double[][] c = new double[n][n];
if (numThreads == 1) {
multiplySequential(a, b, c, 0, n);
} else {
multiplyParallel(a, b, c, numThreads);
}
return c;
}
private static void multiplySequential(double[][] a, double[][] b, double[][] c,
int startRow, int endRow) {
int n = a.length;
for (int i = startRow; i < endRow; i++) {
for (int j = 0; j < n; j++) {
double sum = 0;
for (int k = 0; k < n; k++) {
sum += a[i][k] * b[k][j];
}
c[i][j] = sum;
}
}
}
private static void multiplyParallel(double[][] a, double[][] b, double[][] c, int numThreads) {
int n = a.length;
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
int rowsPerThread = n / numThreads;
for (int t = 0; t < numThreads; t++) {
final int startRow = t * rowsPerThread;
final int endRow = (t == numThreads - 1) ? n : startRow + rowsPerThread;
executor.execute(() -> {
multiplySequential(a, b, c, startRow, endRow);
});
}
executor.shutdown();
try {
executor.awaitTermination(1, TimeUnit.HOURS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Multiplication interrupted", e);
}
}
public static double[][] generateRandomMatrix(int n) {
double[][] matrix = new double[n][n];
Random random = new Random();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
matrix[i][j] = random.nextDouble() * 100;
}
}
return matrix;
}
public static boolean verifyMultiplication(double[][] a, double[][] b, double[][] c) {
int n = a.length;
double[][] expected = multiply(a, b, 1);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (Math.abs(c[i][j] - expected[i][j]) > 1e-9) {
return false;
}
}
}
return true;
}
public static void main(String[] args) {
int[] sizes = {100, 300, 500};
int[] threadConfigs = {1, 2, 4, 8};
System.out.println("Matrix Multiplication Benchmark Results");
System.out.println("======================================");
for (int size : sizes) {
System.out.printf("\nMatrix size: %dx%d%n", size, size);
System.out.println("--------------------------------------");
double[][] a = generateRandomMatrix(size);
double[][] b = generateRandomMatrix(size);
long startTime = System.nanoTime();
double[][] resultSeq = multiply(a, b, 1);
long sequentialTime = System.nanoTime() - startTime;
System.out.printf("Sequential (1 thread): %8.3f ms%n", sequentialTime / 1_000_000.0);
for (int threads : threadConfigs) {
if (threads == 1) continue;
startTime = System.nanoTime();
double[][] resultPar = multiply(a, b, threads);
long parallelTime = System.nanoTime() - startTime;
boolean correct = verifyMultiplication(a, b, resultPar);
double speedup = (double) sequentialTime / parallelTime;
System.out.printf("Parallel (%2d threads): %8.3f ms, Speedup: %5.2fx, Correct: %b%n",
threads, parallelTime / 1_000_000.0, speedup, correct);
}
}
}
}

View File

@@ -0,0 +1,49 @@
# Лабораторная работа 5
**Тема**: Параллельное и последовательное умножение матриц на Java
## Запуск
Нажать на **Run/Debug**
Или
Компилировать через
```bash
javac MatrixMultiplier.java
```
и запускать через
```bash
java MatrixMultiplier
```
## Какие технологии использовал
1. Java 17
2. java.util.concurrent
## Что делает программа
Программа вычисляет определитель квадратной матрицы двумя способами
1. Последовательный алгоритм (в 1 потоке)
2. Параллельный алгоритм (Каждая группа строк обрабатывается в отдельном потоке)
## Задание со звездочкой
* Метод multiply() работает и последовательно, и параллельно в зависимости от параметра numThreads
* При numThreads = 1 выполняется последовательная версия, при numThreads > 1 - параллельная
* Обе версии используют один и тот же вычислительный код в методе multiplySequential()
## Сравнение результатов
![image](image.png)
## Заключение
В заключении можно сказать что параллелизация выгодна только при большом размере матриц, так как накладные расходы на создания потоков значимы при перемножении маленьких матриц
[Видео](https://vkvideo.ru/video-187005855_456239022?list=ln-gBIRXzjfl4HghZPCyv)

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB