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:
196
putincev_daniil_lab_6/Project/MatrixDeterminant.java
Normal file
196
putincev_daniil_lab_6/Project/MatrixDeterminant.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
59
putincev_daniil_lab_6/README.md
Normal file
59
putincev_daniil_lab_6/README.md
Normal 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 - параллельная версия
|
||||
|
||||
## Сравнение результатов
|
||||
|
||||

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