diff --git a/novopolcev_alexander_lab_5/README.md b/novopolcev_alexander_lab_5/README.md new file mode 100644 index 00000000..b5a7a56e --- /dev/null +++ b/novopolcev_alexander_lab_5/README.md @@ -0,0 +1,30 @@ +# Лабораторная работа №5 - Параллельное умножение матриц + +## Задание + + +* Кратко: реализовать умножение двух больших квадратных матриц. + +* Подробно: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный (задание со * - реализовать это в рамках одного алгоритма). В параллельном алгоритме предусмотреть ручное задание количества потоков (число потоков = 1 как раз и реализует задание со *), каждый из которых будет выполнять умножение элементов матрицы в рамках своей зоны ответственности. + +## Работа программы: + + 1. Генерируются случайные матрицы A и B заданных размеров. + + 2. multiply_matrices_sequential(A, B) умножает две матрицы A и B последовательно, используя вложенные циклы для вычисления элементов результирующей матрицы C. + + 3. multiply_matrices_parallel(A, B, num_workers) выполняет параллельное умножение матриц с использованием пула процессов. + + 4. benchmark(matrix_size, num_workers) Измеряет время выполнения операций умножения. И выводит результат в консоль. + +### Результат: + +![](result.jpg "") + +### Вывод: + +При работе с большими матрицами параллельная обработка обычно оказывается эффективнее последовательной благодаря распределению вычислительной нагрузки между несколькими процессорами. Однако при обработке малых матриц затраты на организацию и управление параллельными потоками могут превысить выигрыш от их использования, и тогда последовательная обработка окажется быстрее. + + +# Видео +https://disk.yandex.ru/i/MUL1RGOHfue8wQ diff --git a/novopolcev_alexander_lab_5/main.py b/novopolcev_alexander_lab_5/main.py new file mode 100644 index 00000000..3d159fbd --- /dev/null +++ b/novopolcev_alexander_lab_5/main.py @@ -0,0 +1,61 @@ +import numpy as np +import time +from multiprocessing import Pool + +def multiply_matrices_sequential(A, B): + """Последовательное умножение матриц.""" + n = A.shape[0] + C = np.zeros((n, n)) + for i in range(n): + for j in range(n): + C[i][j] = np.dot(A[i], B[:, j]) # Используем векторизированное умножение для повышения производительности + return C + +def worker(args): + """Функция для параллельного умножения матриц, которая обрабатывает строки.""" + A, B, row_indices = args + C_part = np.zeros((len(row_indices), B.shape[1])) + + for idx, i in enumerate(row_indices): + C_part[idx] = np.dot(A[i], B) + + return C_part + +def multiply_matrices_parallel(A, B, num_workers): + """Параллельное умножение матриц.""" + n = A.shape[0] + C = np.zeros((n, n)) + row_indices = np.array_split(range(n), num_workers) + + with Pool(processes=num_workers) as pool: + results = pool.map(worker, [(A, B, idx) for idx in row_indices]) + + # Объединяем результаты + for i, result in enumerate(results): + C[i * len(result): (i + 1) * len(result)] = result + + return C + +def benchmark(matrix_size, num_workers): + # Генерация случайных матриц + A = np.random.rand(matrix_size, matrix_size) + B = np.random.rand(matrix_size, matrix_size) + + start_time = time.time() + if num_workers == 1: + C = multiply_matrices_sequential(A, B) + else: + C = multiply_matrices_parallel(A, B, num_workers) + end_time = time.time() + + method = "последовательное" if num_workers == 1 else f"параллельное с {num_workers} потоками" + print(f"{method.capitalize()} умножение матриц {matrix_size}x{matrix_size}: {end_time - start_time:.6f} сек") + +if __name__ == "__main__": + # Запуск бенчмарков + sizes = [100, 300, 500] + for size in sizes: + print(f"\nБенчмарк для матриц размером {size}x{size}:") + benchmark(size, 1) # Последовательный + benchmark(size, 4) # Параллельный (4 потока) + benchmark(size, 8) # Параллельный (8 потоков) diff --git a/novopolcev_alexander_lab_5/result.jpg b/novopolcev_alexander_lab_5/result.jpg new file mode 100644 index 00000000..53bf718f Binary files /dev/null and b/novopolcev_alexander_lab_5/result.jpg differ