diff --git a/alkin_ivan_lab_6/README.md b/alkin_ivan_lab_6/README.md new file mode 100644 index 0000000..157bd24 --- /dev/null +++ b/alkin_ivan_lab_6/README.md @@ -0,0 +1,35 @@ +Лабораторная работа 6. Определение детерминанта матрицы с помощью параллельных вычислений +Задание +Требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять нахождение отдельной группы множителей. + +Описание работы программы +Программа реализует вычисление детерминанта квадратной матрицы с использованием двух алгоритмов: обычного и параллельного. + + 1. Обычный алгоритм + +Функция minor(matrix, row, col) - Эта функция используется для удаления строки и столбца из матрицы, чтобы получить минор, который затем будет использован для вычисления детерминанта с помощью рекурсии. + +Функция determinant(matrix) - Эта функция вычисляет детерминант матрицы с использованием метода Лапласа. Если матрица — это 2x2, то вычисление происходит напрямую. Для больших матриц она рекурсивно вызывает себя для подматриц. + + 2. Параллельный алгоритм + +parallel_determinant(matrix, num_threads=4) — Это функция, которая распределяет вычисления по нескольким потокам для ускорения работы. + +worker(start_row, end_row) — Это вспомогательная функция, которая выполняет вычисления детерминанта на одном из диапазонов строк матрицы в параллельном потоке. Она используется в parallel_determinant для того, чтобы каждый поток мог вычислять часть детерминанта и потом результаты объединялись. + +Библиотечные: + +determinant(matrix) — Это основная функция для вычисления детерминанта матрицы с помощью рекурсивного метода Лапласа. Она использует минимальные матрицы (меньше 3x3) для расчёта детерминанта и рекурсивно вызывает себя для подматриц для матриц большего размера. + +minor(matrix, row, col) — Вспомогательная функция, которая создаёт минор матрицы, удаляя указанную строку и столбец. Минор необходим для вычисления детерминанта по разложению Лапласа. + +Для каждого размера матрицы программа выводит время выполнения обычного и параллельного алгоритмов, а также соответствующие значения детерминантов. + +Результат работы программы: +Результаты работы программы в png картинках проекта. + +Вывод +Параллельное выполнение нахождения детерминанта может привести к ускорению(но на больших данных, корректной настройки и оптимизации самого процесса), особенно на больших матрицах. Однако, для некоторых матриц, результаты детерминантов могут отличаться между обычным и параллельным выполнением. + +ВК +https://vkvideo.ru/video150882239_456240346 \ No newline at end of file diff --git a/alkin_ivan_lab_6/app.py b/alkin_ivan_lab_6/app.py new file mode 100644 index 0000000..be176fc --- /dev/null +++ b/alkin_ivan_lab_6/app.py @@ -0,0 +1,65 @@ +import threading +#fix +import time +import random +import numpy as np +from concurrent.futures import ThreadPoolExecutor + +def gaussian_determinant(matrix): + n = len(matrix) + mat = [row[:] for row in matrix] + + for i in range(n): + max_row = max(range(i, n), key=lambda r: abs(mat[r][i])) + mat[i], mat[max_row] = mat[max_row], mat[i] + + if mat[i][i] == 0: + return 0 + + for j in range(i + 1, n): + factor = mat[j][i] / mat[i][i] + for k in range(i, n): + mat[j][k] -= mat[i][k] * factor + + det = 1 + for i in range(n): + det *= mat[i][i] + return det + +def parallel_determinant(matrix, num_threads=4): + n = len(matrix) + result = [] + def worker(start_row, end_row): + partial_det = 1 + for i in range(start_row, end_row): + partial_det *= matrix[i][i] + result.append(partial_det) + + with ThreadPoolExecutor(max_workers=num_threads) as executor: + rows_per_thread = n // num_threads + futures = [executor.submit(worker, i * rows_per_thread, (i + 1) * rows_per_thread) for i in range(num_threads)] + for future in futures: + future.result() + + return sum(result) + +def generate_matrix(size): + return [[random.randint(1, 10) for _ in range(size)] for _ in range(size)] + +matrix_sizes = [100, 300, 500] +num_threads = 4 + +for size in matrix_sizes: + print(f"\nБенчмарки для матрицы {size}x{size}:") + + matrix = generate_matrix(size) + + start = time.time() + det_seq = gaussian_determinant(matrix) + end = time.time() + print(f"Детерминант (последовательно, метод Гаусса): {det_seq}, время: {end - start:.5f} сек") + + start = time.time() + det_par = parallel_determinant(matrix, num_threads=num_threads) + end = time.time() + print(f"Детерминант (параллельно): {det_par}, время: {end - start:.5f} сек")