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:
121
putincev_daniil_lab_5/Project/MatrixMultiplier.java
Normal file
121
putincev_daniil_lab_5/Project/MatrixMultiplier.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
49
putincev_daniil_lab_5/README.md
Normal file
49
putincev_daniil_lab_5/README.md
Normal 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()
|
||||
|
||||
## Сравнение результатов
|
||||
|
||||

|
||||
|
||||
## Заключение
|
||||
|
||||
В заключении можно сказать что параллелизация выгодна только при большом размере матриц, так как накладные расходы на создания потоков значимы при перемножении маленьких матриц
|
||||
|
||||
[Видео](https://vkvideo.ru/video-187005855_456239022?list=ln-gBIRXzjfl4HghZPCyv)
|
||||
BIN
putincev_daniil_lab_5/image.png
Normal file
BIN
putincev_daniil_lab_5/image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Reference in New Issue
Block a user