From 04337dc788bf833ef35d50c87ac928cf9633de47 Mon Sep 17 00:00:00 2001 From: superhugebetformiladze Date: Mon, 22 Jan 2024 04:58:35 +0400 Subject: [PATCH] simonov nikita lab 6 ready --- simonov_nikita_lab_6/main.py | 63 ++++++++++++++++++ simonov_nikita_lab_6/readme.md | 21 ++++++ simonov_nikita_lab_6/screens/Screenshot_1.png | Bin 0 -> 24717 bytes 3 files changed, 84 insertions(+) create mode 100644 simonov_nikita_lab_6/main.py create mode 100644 simonov_nikita_lab_6/readme.md create mode 100644 simonov_nikita_lab_6/screens/Screenshot_1.png diff --git a/simonov_nikita_lab_6/main.py b/simonov_nikita_lab_6/main.py new file mode 100644 index 0000000..72d371e --- /dev/null +++ b/simonov_nikita_lab_6/main.py @@ -0,0 +1,63 @@ +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, num_runs=5): + # Генерация квадратной матрицы + matrix = np.random.rand(matrix_size, matrix_size) + + # Бенчмарк для обычного нахождения детерминанта + normal_runtimes = [] + for _ in range(num_runs): + start_time = time.time() + det_normal = calculate_determinant(matrix) + end_time = time.time() + normal_runtimes.append(end_time - start_time) + + avg_normal_runtime = np.mean(normal_runtimes) + print(f"Размер матрицы {matrix_size}x{matrix_size}") + print(f"Среднее время при обычном выполнении ({num_runs} запусков): {avg_normal_runtime:.6f} секунд") + print(f"Детерминант: {det_normal}") + + # Бенчмарк для параллельного нахождения детерминанта + parallel_runtimes = [] + for _ in range(num_runs): + start_time = time.time() + det_parallel = calculate_determinant_parallel(matrix, num_threads) + end_time = time.time() + parallel_runtimes.append(end_time - start_time) + + avg_parallel_runtime = np.mean(parallel_runtimes) + print(f"Среднее время при параллельном выполнении ({num_threads} поток, {num_runs} запусков): {avg_parallel_runtime:.6f} секунд") + print(f"Детерминант: {det_parallel}") + + # Процентное ускорение + speedup = avg_normal_runtime / avg_parallel_runtime + print(f"Процентное ускорение: {speedup * 100:.2f}%\n") + +# Запуск бенчмарков для разных размеров матриц +benchmark(100) +benchmark(300) +benchmark(500) diff --git a/simonov_nikita_lab_6/readme.md b/simonov_nikita_lab_6/readme.md new file mode 100644 index 0000000..aba9f5e --- /dev/null +++ b/simonov_nikita_lab_6/readme.md @@ -0,0 +1,21 @@ +# Лабораторная работа №6. + +## Задание + +В лабораторной работе требуется сделать два алгоритма: обычный и параллельный (задание со * - реализовать это в рамках одного алгоритма). В параллельном алгоритме предусмотреть ручное задание количества потоков (число потоков = 1 как раз и реализует задание со *), каждый из которых будет выполнять нахождение отдельной группы множителей. + +## Ход выполнения + +Программа для проведения бенчмарка вычисления детерминанта матрицы с использованием библиотеки NumPy. Программа оценивает производительность как последовательного, так и параллельного методов вычисления детерминанта. + +- `calculate_determinant(matrix)`: Функция для вычисления детерминанта с использованием библиотеки NumPy. +- `calculate_determinant_parallel(matrix, num_threads)`: Функция для параллельного вычисления детерминанта. +- `benchmark(matrix_size, num_threads=1, num_runs=5)`: Функция для проведения бенчмарка, включающая подробные метрики и информацию о производительности. + +## Результаты + +![](screens/Screenshot_1.png) + +## Ссылка на видео + +https://drive.google.com/file/d/14ve4Xq26waLWCLlXunmnMPWFltNudsbr/view?usp=sharing \ No newline at end of file diff --git a/simonov_nikita_lab_6/screens/Screenshot_1.png b/simonov_nikita_lab_6/screens/Screenshot_1.png new file mode 100644 index 0000000000000000000000000000000000000000..3b055bfa608361c7570152f51d074b67b817eaa2 GIT binary patch literal 24717 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 KrRemfTmJ?W4;H}y literal 0 HcmV?d00001