diff --git a/kurushina_ksenia_lab_6/README.md b/kurushina_ksenia_lab_6/README.md new file mode 100644 index 0000000..462b3c9 --- /dev/null +++ b/kurushina_ksenia_lab_6/README.md @@ -0,0 +1,53 @@ +# Лабораторная работа №6: Определение детерминанта матрицы с использованием параллельных вычислений + +## **Задание** +Необходимо разработать два алгоритма для вычисления детерминанта квадратной матрицы: +1. **Обычный алгоритм** — выполняется последовательно. +2. **Параллельный алгоритм** — с возможностью ручного задания количества потоков. Каждый поток отвечает за вычисление определённой группы множителей. + +--- + +## **Описание работы программы** +Программа предназначена для вычисления детерминанта квадратной матрицы двумя способами: +- **Обычным (последовательным)** методом. +- **Параллельным**, который ускоряет выполнение за счёт многопоточности. + +### **Обычный алгоритм** +1. **`minor(matrix, row, col)`** + - Вспомогательная функция для формирования минора матрицы. Удаляет указанную строку и столбец, подготавливая данные для рекурсивного вычисления. + +2. **`determinant(matrix)`** + - Основная функция для вычисления детерминанта. Использует метод разложения Лапласа. + - Для матриц 2x2 результат вычисляется напрямую. + - Для матриц большего размера рекурсивно вызывает себя для вычисления детерминантов подматриц. + +### **Параллельный алгоритм** +1. **`parallel_determinant(matrix, num_threads=4)`** + - Основная функция, распределяющая вычисления детерминанта между потоками. + - Количество потоков задаётся вручную. + +2. **`worker(start_row, end_row)`** + - Вспомогательная функция, используемая потоками. Выполняет вычисления на заданном диапазоне строк. + - Результаты отдельных потоков объединяются для получения итогового детерминанта. + +--- + +## **Особенности реализации** +- Вычисления для небольших матриц выполняются быстрее обычным алгоритмом. +- Параллельный подход показывает значительное ускорение при обработке больших матриц (при оптимальной настройке количества потоков). + +--- + +## **Результаты работы** + +Для каждой матрицы программа выводит: +- Значение детерминанта, рассчитанное обоими алгоритмами. +- Время выполнения для каждого из методов. + +Результаты тестирования представлены в виде графиков и таблиц, сохранённых в PNG-файлах проекта. + +--- + +## **Видео** + +https://cloud.mail.ru/public/L7Wf/o3nkwpAGx \ No newline at end of file diff --git a/kurushina_ksenia_lab_6/img.png b/kurushina_ksenia_lab_6/img.png new file mode 100644 index 0000000..2a8a840 Binary files /dev/null and b/kurushina_ksenia_lab_6/img.png differ diff --git a/kurushina_ksenia_lab_6/main.py b/kurushina_ksenia_lab_6/main.py new file mode 100644 index 0000000..be176fc --- /dev/null +++ b/kurushina_ksenia_lab_6/main.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} сек")