afanasev_dmitry_lab_6 is ready #242

Merged
Alexey merged 1 commits from afanasev_dmitry_lab_6 into main 2024-12-15 13:33:08 +04:00
2 changed files with 149 additions and 0 deletions
Showing only changes of commit 90206c821f - Show all commits

View File

@ -0,0 +1,118 @@
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FastDeterminantCalculator {
public static void main(String[] args) {
int[] sizes = {100, 300, 500};
int[] threads = {1, 4, 8, 10};
for (int size : sizes) {
BigDecimal[][] matrix = generateMatrix(size);
for (int threadCount : threads) {
long start = System.currentTimeMillis();
BigDecimal determinant = calculateDeterminant(matrix, threadCount);
long end = System.currentTimeMillis();
System.out.printf("Matrix size: %dx%d, Threads: %d, Time: %d ms\n",
size, size, threadCount, (end - start));
}
}
}
public static BigDecimal[][] generateMatrix(int size) {
BigDecimal[][] matrix = new BigDecimal[size][size];
for (int i = 0; i < size; i++) {
BigDecimal rowSum = BigDecimal.ZERO;
for (int j = 0; j < size; j++) {
matrix[i][j] = BigDecimal.valueOf(Math.random() * 10);
if (i != j) {
rowSum = rowSum.add(matrix[i][j]);
}
}
matrix[i][i] = rowSum.add(BigDecimal.valueOf(Math.random() * 10 + 1));
}
return matrix;
}
public static BigDecimal calculateDeterminant(BigDecimal[][] matrix, int threadCount) {
int size = matrix.length;
BigDecimal[][] lu = new BigDecimal[size][size];
int[] permutations = new int[size];
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
if (!luDecomposition(matrix, lu, permutations, executor)) {
executor.shutdown();
return BigDecimal.ZERO; // Матрица вырожденная
}
executor.shutdown();
BigDecimal determinant = BigDecimal.ONE;
for (int i = 0; i < size; i++) {
determinant = determinant.multiply(lu[i][i]);
if (permutations[i] != i) {
determinant = determinant.negate(); // Меняем знак при перестановке
}
}
return determinant;
}
public static boolean luDecomposition(BigDecimal[][] matrix, BigDecimal[][] lu, int[] permutations, ExecutorService executor) {
int size = matrix.length;
for (int i = 0; i < size; i++) {
System.arraycopy(matrix[i], 0, lu[i], 0, size);
permutations[i] = i;
}
for (int k = 0; k < size; k++) {
int pivot = k;
for (int i = k + 1; i < size; i++) {
if (lu[i][k].abs().compareTo(lu[pivot][k].abs()) > 0) {
pivot = i;
}
}
if (lu[pivot][k].abs().compareTo(BigDecimal.valueOf(1e-10)) < 0) {
return false;
}
if (pivot != k) {
BigDecimal[] temp = lu[k];
lu[k] = lu[pivot];
lu[pivot] = temp;
int tempPerm = permutations[k];
permutations[k] = permutations[pivot];
permutations[pivot] = tempPerm;
}
CountDownLatch latch = new CountDownLatch(size - k - 1);
for (int i = k + 1; i < size; i++) {
int row = i;
int finalK = k;
executor.submit(() -> {
MathContext mc = new MathContext(20, RoundingMode.HALF_UP);
lu[row][finalK] = lu[row][finalK].divide(lu[finalK][finalK], mc);
for (int j = finalK + 1; j < size; j++) {
lu[row][j] = lu[row][j].subtract(lu[row][finalK].multiply(lu[finalK][j], mc));
}
latch.countDown();
});
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,31 @@
# Лабораторная работа 6
## Описание
Задание заключается в реализации алгоритмов нахождения детерминанта квадратной матрицы. Необходимо разработать два алгоритма: последовательный и параллельный. А также провести бенчмарки, а затем описать результаты в отчете.
**100x100 матрица**:
- **8 потоков** — наилучший результат.
- **10 потоков** — результат немного хуже.
- **4 потока** — примерно такой же результат как на 10 потоках.
- **1 поток** — наихудший результат.
**300x300 матрица**:
- **10 потока** — лучший результат.
- **8 потоков** — чуть хуже.
- **4 потока** — ещё медленее.
- **1 поток** — наихудший результат.
**500x500 матрица**:
- **10 потока** — лучший результат.
- **8 потоков** — чуть хуже.
- **4 потока** — ещё медленее.
- **1 поток** — наихудший результат.
**Ссылка на демонстрацию работы программы**: https://vkvideo.ru/video215756667_456239456?list=ln-W6TTsYuIRdX8ft7ADr
**Вывод**:
- Если операция сложнее, рост производительности происходит с увеличением числа потоков.
- Слишком много потоков увеличивает накладные расходы (замтено только на неочень сложных операциях). Это может быть связано, например, с:
1. **Переключением контекстов**: Когда потоков больше, чем ядер процессора, операционная система часто переключает контексты, что занимает время.
2. **Конкуренцией за ресурсы**: Много потоков конкурируют за ограниченные ресурсы, такие как процессорное время и кэш.
3. **Управлением потоками**: С увеличением числа потоков растёт нагрузка на систему, связанную с их созданием, управлением и завершением.