DAS_2023_1/belyaeva_ekaterina_lab_6/README.md
2024-01-11 20:25:40 +04:00

105 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Лабораторная работа №6
## Задание
Кратко: реализовать нахождение детерминанта квадратной матрицы.
Подробно: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять нахождение отдельной группы множителей.
## Ход работы
### Обычный алгоритм
```
private static BigDecimal findDeterminantGauss(double[][] matrix) {
int n = matrix.length;
BigDecimal det = BigDecimal.ONE;
for (int i = 0; i < n; i++) {
int maxRow = i;
for (int j = i + 1; j < n; j++) {
if (Math.abs(matrix[j][i]) > Math.abs(matrix[maxRow][i])) {
maxRow = j;
}
}
if (maxRow != i) {
double[] temp = matrix[i];
matrix[i] = matrix[maxRow];
matrix[maxRow] = temp;
det = det.multiply(BigDecimal.valueOf(-1));
}
for (int j = i + 1; j < n; j++) {
double factor = matrix[j][i] / matrix[i][i];
for (int k = i; k < n; k++) {
matrix[j][k] -= factor * matrix[i][k];
}
}
}
for (int i = 0; i < n; i++) {
det = det.multiply(BigDecimal.valueOf(matrix[i][i]));
}
return det;
}
```
### Параллельный алгоритм
```
private static BigDecimal findDeterminantGaussParallel(double[][] matrix, int threadsCount) {
int n = matrix.length;
final BigDecimal[] det = {BigDecimal.ONE};
ExecutorService executor = Executors.newFixedThreadPool(threadsCount);
for (int i = 0; i < n; i++) {
final int rowIdx = i;
int maxRow = rowIdx;
for (int j = rowIdx + 1; j < n; j++) {
if (Math.abs(matrix[j][rowIdx]) > Math.abs(matrix[maxRow][rowIdx])) {
maxRow = j;
}
}
if (maxRow != rowIdx) {
double[] temp = matrix[rowIdx];
matrix[rowIdx] = matrix[maxRow];
matrix[maxRow] = temp;
det[0] = det[0].multiply(BigDecimal.valueOf(-1));
}
executor.execute(() -> {
for (int j = rowIdx + 1; j < n; j++) {
double factor = matrix[j][rowIdx] / matrix[rowIdx][rowIdx];
for (int k = rowIdx; k < n; k++) {
matrix[j][k] -= factor * matrix[rowIdx][k];
}
}
});
det[0] = det[0].multiply(BigDecimal.valueOf(matrix[rowIdx][rowIdx]));
}
executor.shutdown();
try {
executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
return det[0];
}
```
## Результат
Была проверка времени выполнения алгоритма для матриц размером 100х100, 300х300, 500х500 с разным количеством потоков.
![img.png](img.png)
Из данного скриншота можно сделать вывод, что нахождение детерминанта для матрицы:
- 100х100 - обычный алгоритм работает лучше параллельного, но разница не сказать что значительная
- 300х300 - обычный алгоритм работает хуже параллельного, но при добавлении потоков параллельный алгоритм работает чуть хуже
- 500х500 - обычный алгоритм работает значительно лучше параллельного, но параллельный начинает показывать себя лучше при увеличении количества потоков (но обычный алгоритм все равно лучше)
Работоспособность показана в видео: [lab6.mp4](lab6.mp4)