From 2347b3c3cdbd9aa85ca23403f08e176ecaf4e0d8 Mon Sep 17 00:00:00 2001 From: enuementtt Date: Tue, 16 Jan 2024 19:24:25 +0400 Subject: [PATCH] romanova_adelina_lab_6_ready --- romanova_adelina_lab_6/README.md | 37 ++++++++++++++++++++++ romanova_adelina_lab_6/main.py | 49 ++++++++++++++++++++++++++++++ romanova_adelina_lab_6/result.png | Bin 0 -> 26607 bytes 3 files changed, 86 insertions(+) create mode 100644 romanova_adelina_lab_6/README.md create mode 100644 romanova_adelina_lab_6/main.py create mode 100644 romanova_adelina_lab_6/result.png diff --git a/romanova_adelina_lab_6/README.md b/romanova_adelina_lab_6/README.md new file mode 100644 index 0000000..d2b7084 --- /dev/null +++ b/romanova_adelina_lab_6/README.md @@ -0,0 +1,37 @@ +# Лабораторная работа 6. Определение детерминанта матрицы с помощью параллельных вычислений + +## Задание + +Требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять нахождение отдельной группы множителей. + +### Запуск программы + +Для запуска программы необходимо с помощью командной строки в корневой директории файлов прокета прописать: +``` +python main.py +``` + +### Описание работы программы + +Программа реализует вычисление детерминанта квадратной матрицы с использованием двух алгоритмов: *обычного и параллельного*. + +  1. Обычный алгоритм + +      Использует функцию ```numpy.linalg.det()``` для вычисления детерминанта. + +  2. Параллельный алгоритм + +      Разбивает матрицу на части и использует несколько потоков для параллельного вычисления детерминанта. Количество потоков задается вручную. Реализован с использованием библиотеки ```concurrent.futures```. + +Для каждого размера матрицы программа выводит время выполнения обычного и параллельного алгоритмов, а также соответствующие значения детерминантов. + +### Результат работы программы: + +![](result.png "") + +#### Вывод + +Параллельное выполнение нахождения детерминанта может привести к ускорению, особенно на больших матрицах. Однако, для некоторых матриц, результаты детерминантов могут отличаться между обычным и параллельным выполнением. + +# Youtube +https://youtu.be/2HcM0LfTgQk \ No newline at end of file diff --git a/romanova_adelina_lab_6/main.py b/romanova_adelina_lab_6/main.py new file mode 100644 index 0000000..fed1e97 --- /dev/null +++ b/romanova_adelina_lab_6/main.py @@ -0,0 +1,49 @@ +import numpy as np +import time +import concurrent.futures + +def calculate_determinant(matrix): + return np.linalg.det(matrix) + +def calculate_determinant_parallel(matrix, num_threads): + result = 1.0 + chunk_size = matrix.shape[0] // num_threads + + def calculate_chunk(start, end): + nonlocal result + for i in range(start, end): + result *= matrix[i, i] + + with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor: + futures = [] + for i in range(0, matrix.shape[0], chunk_size): + futures.append(executor.submit(calculate_chunk, i, i + chunk_size)) + + for future in concurrent.futures.as_completed(futures): + future.result() + + return result + +def benchmark(matrix_size, num_threads=1): + # Генерация квадратной матрицы + matrix = np.random.rand(matrix_size, matrix_size) + + # Бенчмарк для обычного нахождения детерминанта + start_time = time.time() + det_normal = calculate_determinant(matrix) + end_time = time.time() + print(f"Размер матрицы {matrix_size}x{matrix_size}") + print(f"Время при обычном выполнении: {end_time - start_time:.6f} секунд") + print(f"Детерминант: {det_normal}") + + # Бенчмарк для параллельного нахождения детерминанта + start_time = time.time() + det_parallel = calculate_determinant_parallel(matrix, num_threads) + end_time = time.time() + print(f"Время при параллельном выполнении ({num_threads} поток): {end_time - start_time:.6f} секунд") + print(f"Детерминант: {det_parallel}\n") + +# Запуск бенчмарков +benchmark(100) +benchmark(300) +benchmark(500) diff --git a/romanova_adelina_lab_6/result.png b/romanova_adelina_lab_6/result.png new file mode 100644 index 0000000000000000000000000000000000000000..69f26f4552057b966f52820e9d7484661d86e1ad GIT binary patch literal 26607 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 literal 0 HcmV?d00001 -- 2.25.1