DAS_2023_1/podkorytova_yulia_lab_6/README.md
2024-01-10 16:37:46 +04:00

5.0 KiB
Raw Blame History

Лабораторная работа 6. Параллельный поиск значения детерминанта матрицы

Задание на лабораторную работу

Кратко: реализовать нахождение детерминанта квадратной матрицы.

Подробно: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять нахождение отдельной группы множителей.


Описание работы

Обычный алгоритм реализован в методе findDeterminantSequential класса Main (путь до файла: /app/src/Main.java):

private static int findDeterminantSequential(int[][] matrix) {
    int size = matrix.length;
    int determinant = 0;

    if (size == 1) {
        determinant = matrix[0][0];
    } else if (size == 2) {
        determinant = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
    } else {
        for (int i = 0; i < size; i++) {
            int[][] subMatrix = new int[size - 1][size - 1];
            for (int j = 1; j < size; j++) {
                for (int k = 0; k < size; k++) {
                    if (k < i) {
                        subMatrix[j - 1][k] = matrix[j][k];
                    } else if (k > i) {
                        subMatrix[j - 1][k - 1] = matrix[j][k];
                    }
                }
            }
            determinant += Math.pow(-1, i) * matrix[0][i] * findDeterminantSequential(subMatrix);
        }
    }

    return determinant;
}

Параллельный алгоритм реализован в методе findDeterminantParallel класса Main (путь до файла: /app/src/Main.java):

private static int findDeterminantParallel(int[][] matrix, int threadCount) throws InterruptedException {
    int size = matrix.length;
    int determinant = 0;

    if (size == 1) {
        determinant = matrix[0][0];
    }
    else if (size == 2) {
        determinant = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
    }
    else {
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);

        int[] subDeterminants = new int[size];
        for (int i = 0; i < size; i++) {
            int[][] subMatrix = new int[size - 1][size - 1];
            for (int j = 1; j < size; j++) {
                for (int k = 0; k < size; k++) {
                    if (k < i) {
                        subMatrix[j - 1][k] = matrix[j][k];
                    } else if (k > i) {
                        subMatrix[j - 1][k - 1] = matrix[j][k];
                    }
                }
            }
            final int row = i;
            executor.submit(() -> {
                subDeterminants[row] = findDeterminantSequential(subMatrix);
            });
        }

        executor.shutdown();
        try {
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        for (int i = 0; i < size; i++) {
            determinant += matrix[0][i] * Math.pow(-1, i) * subDeterminants[i];
        }
    }

    return determinant;
}

В методе создается пул потоков с помощью ExecutorService и указанным количеством потоков threadCount. Класс ExecutorService используется для управления потоками, методы shutdown и awaitTermination используются для корректного завершения работы потоков. Метод findDeterminantSequential используется для вычисления подопределителей в каждом потоке.


Результаты

Результат работы

На матрицах размером от 5x5 до 8x8 последовательный алгоритм справляется быстрее параллельного, а на матрицах размером 9x9 и больше параллельный алгоритм справляется быстрее последовательного.

Вывод: при вычислении детерминантов квадратных матриц небольших размеров использование параллельного алгоритма дает проигрыш в производительности использованию последовательного алгоритма. Параллельное умножение матриц будет эффективнее, если размер матриц больше, чем 9x9.

Ссылка на видео:

https://drive.google.com/file/d/1cN41hHbEbeRizf0qSu1EE8LEHAL1Src1/view?usp=sharing