Merge pull request 'putincev_daniil_lab_6' (#394) from putincev_daniil_lab_6 into main

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

View File

@@ -0,0 +1,196 @@
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MatrixDeterminant {
public static double determinant(double[][] matrix, int numThreads) {
int n = matrix.length;
if (n == 0 || matrix[0].length != n) {
throw new IllegalArgumentException("Matrix must be square");
}
double[][] workingMatrix = copyMatrix(matrix);
if (numThreads == 1) {
return determinantSequential(workingMatrix);
} else {
return determinantParallel(workingMatrix, numThreads);
}
}
private static double determinantSequential(double[][] matrix) {
int n = matrix.length;
double det = 1.0;
for (int i = 0; i < n; i++) {
int maxRow = i;
for (int k = i + 1; k < n; k++) {
if (Math.abs(matrix[k][i]) > Math.abs(matrix[maxRow][i])) {
maxRow = k;
}
}
if (Math.abs(matrix[maxRow][i]) < 1e-12) return 0.0;
if (maxRow != i) {
swapRows(matrix, i, maxRow);
det *= -1;
}
det *= matrix[i][i];
if (i < n - 1) {
double divisor = matrix[i][i];
for (int k = i + 1; k < n; k++) {
double factor = matrix[k][i] / divisor;
for (int j = i + 1; j < n; j++) {
matrix[k][j] -= factor * matrix[i][j];
}
}
}
}
return det;
}
private static double determinantParallel(double[][] matrix, int numThreads) {
int n = matrix.length;
double det = 1.0;
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
try {
for (int pivot = 0; pivot < n; pivot++) {
int maxRow = pivot;
for (int k = pivot + 1; k < n; k++) {
if (Math.abs(matrix[k][pivot]) > Math.abs(matrix[maxRow][pivot])) {
maxRow = k;
}
}
if (Math.abs(matrix[maxRow][pivot]) < 1e-12) return 0.0;
if (maxRow != pivot) {
swapRows(matrix, pivot, maxRow);
det *= -1;
}
det *= matrix[pivot][pivot];
if (pivot < n - 1) {
final int currentPivot = pivot;
final double divisor = matrix[pivot][pivot];
CountDownLatch latch = new CountDownLatch(numThreads);
for (int t = 0; t < numThreads; t++) {
final int threadId = t;
executor.execute(() -> {
try {
for (int row = currentPivot + 1 + threadId; row < n; row += numThreads) {
double factor = matrix[row][currentPivot] / divisor;
for (int col = currentPivot + 1; col < n; col++) {
matrix[row][col] -= factor * matrix[currentPivot][col];
}
}
} finally {
latch.countDown();
}
});
}
latch.await();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return 0.0;
} finally {
executor.shutdown();
}
return det;
}
private static void swapRows(double[][] matrix, int row1, int row2) {
double[] temp = matrix[row1];
matrix[row1] = matrix[row2];
matrix[row2] = temp;
}
private static double[][] copyMatrix(double[][] matrix) {
int n = matrix.length;
double[][] copy = new double[n][n];
for (int i = 0; i < n; i++) {
System.arraycopy(matrix[i], 0, copy[i], 0, n);
}
return copy;
}
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 = i; j < n; j++) {
matrix[i][j] = random.nextDouble() * 2.0 + 0.1;
}
}
double det = 1.0;
for (int i = 0; i < n; i++) {
det *= matrix[i][i];
}
return matrix;
}
public static void main(String[] args) {
int[] sizes = {100, 300, 500, 1000, 2000};
int[] threadConfigs = {1, 2, 4, 8};
System.out.println("\nMatrix Determinant Benchmark Results");
System.out.println("===================================");
for (int size : sizes) {
System.out.printf("Matrix size: %dx%d%n", size, size);
System.out.println("-----------------------------------");
double[][] matrix = generateRandomMatrix(size);
double referenceDet = determinantSequential(copyMatrix(matrix));
for (int threads : threadConfigs) {
double[][] testMatrix = copyMatrix(matrix);
long startTime = System.nanoTime();
double calculatedDet = determinant(testMatrix, threads);
long endTime = System.nanoTime();
long duration = endTime - startTime;
boolean correct = Math.abs(referenceDet - calculatedDet) < 1e-6;
if (threads == 1) {
System.out.printf("Sequential: %8.3f ms, Determinant: %.6e, Correct: %b%n",
duration / 1_000_000.0, calculatedDet, correct);
} else {
double[][] seqMatrix = copyMatrix(matrix);
long seqStart = System.nanoTime();
double seqDet = determinant(seqMatrix, 1);
long seqDuration = System.nanoTime() - seqStart;
double speedup = (double) seqDuration / duration;
double efficiency = (speedup / threads) * 100;
System.out.printf("Parallel (%d threads): %8.3f ms, Determinant: %.6e, Speedup: %5.2fx, Efficiency: %5.1f%%, Correct: %b%n",
threads, duration / 1_000_000.0, calculatedDet, speedup, efficiency, correct);
}
}
System.out.println();
}
}
}

View File

@@ -0,0 +1,59 @@
# Лабораторная работа 6
**Тема**: Нахождение детерминанта квадратной матрицы
## Запуск
Нажать на **Run/Debug**
Или
Компилировать через
```bash
javac MatrixMultiplier.java
```
и запускать через
```bash
java MatrixMultiplier
```
## Технологии
1. Java 21
2. java.util.concurrent
## Что делает программа
Программа вычисляет определитель квадратной матрицы двумя способами:
1. Последовательный алгоритм (в 1 потоке)
2. Параллельный алгоритм (используется несколько потоков для обработки)
### Алгоритм
* Использует метод Гаусса с выбором ведущего элемента
* Приводит матрицу к верхнетреугольному виду
* Определитель = произведение диагональных элементов (с учетом перестановок строк)
### Параллельность
* Распараллеливает самую тяжелую часть - обнуление элементов под ведущим
* Каждый поток обрабатывает свой набор строк
## Задание со звездочкой
Один метод determinant() работает в двух режимах
* numThreads = 1 - последовательная версия
* numThreads > 1 - параллельная версия
## Сравнение результатов
![image](image.png)
## Заключение
В заключение можно сказать что в отличии от прошлой лабораторной - паралелльный алгоритм не такой выгодный. Плюсы параллелизации становяться видны только после матриц 1000х1000
[Видео](https://vkvideo.ru/video-187005855_456239023?list=ln-VoDJBv4s1t4YDRZGSc)

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB