diff --git a/putilin_pavel_lab_5/README.md b/putilin_pavel_lab_5/README.md new file mode 100644 index 0000000..657515d --- /dev/null +++ b/putilin_pavel_lab_5/README.md @@ -0,0 +1,37 @@ +# Лабораторная работа №5: Вспоминаем математику или параллельное перемножение матриц + +## Задание + +Реализовать умножение двух квадратных матриц двумя способами: обычным и параллельным. +В параллельном алгоритме предусмотреть возможность задания количества потоков. +Каждый поток должен выполнять умножение матрицы в своей зоне ответственности. + +### Требования: +1. Обычное умножение матриц. +2. Параллельное умножение с ручным заданием количества потоков. +3. Бенчмаркинг для матриц размером 100x100, 300x300 и 500x500. + +## Структура проекта + +Проект реализован в одном файле `main.py`. В нем содержатся: +- Обычное умножение матриц. +- Параллельное умножение с использованием многозадачности. +- Генерация случайных матриц для тестирования. +- Бенчмаркинг для проверки времени выполнения обоих алгоритмов. +- Тесты для проверки корректности умножения. + +## Видео + +https://cloud.mail.ru/public/Wzc4/FZCUnh5mk + +## Заключение + +В ходе лабораторной работы были реализованы два алгоритма умножения матриц: +обычный и параллельный. Параллельное умножение показало +значительное ускорение при больших матрицах. +Ожидаемо, для маленьких матриц разница +в производительности между алгоритмами была незначительной. +Параллельное умножение эффективно использует многозадачность +для уменьшения времени выполнения на крупных матрицах. + + diff --git a/putilin_pavel_lab_5/main.py b/putilin_pavel_lab_5/main.py new file mode 100644 index 0000000..e567ee7 --- /dev/null +++ b/putilin_pavel_lab_5/main.py @@ -0,0 +1,108 @@ +import random +import time +import multiprocessing + +def matrix_multiply(A, B): + + rows_A = len(A) + cols_A = len(A[0]) + cols_B = len(B[0]) + + if len(B) != cols_A: + raise ValueError("Количество столбцов первой матрицы должно совпадать с количеством строк второй матрицы.") + + result = [[0] * cols_B for _ in range(rows_A)] + + for i in range(rows_A): + for j in range(cols_B): + for k in range(cols_A): + result[i][j] += A[i][k] * B[k][j] + + return result + +def parallel_multiply_worker(A, B, result, row_index, cols_A, cols_B): + + for j in range(cols_B): + result[row_index][j] = sum(A[row_index][k] * B[k][j] for k in range(cols_A)) + + +def parallel_matrix_multiply(A, B, num_threads): + + rows_A = len(A) + cols_A = len(A[0]) + cols_B = len(B[0]) + + if len(B) != cols_A: + raise ValueError("Количество столбцов первой матрицы должно совпадать с количеством строк второй матрицы.") + + result = [[0] * cols_B for _ in range(rows_A)] + + processes = [] + for i in range(rows_A): + p = multiprocessing.Process(target=parallel_multiply_worker, args=(A, B, result, i, cols_A, cols_B)) + processes.append(p) + p.start() + + for p in processes: + p.join() + + return result + +def generate_matrix(rows, cols): + return [[random.randint(1, 10) for _ in range(cols)] for _ in range(rows)] + +def benchmark_matrix_multiplication(): + sizes = [100, 300, 500] + num_threads = 4 + + for size in sizes: + print(f"Размер матрицы: {size}x{size}") + + A = generate_matrix(size, size) + B = generate_matrix(size, size) + + start_time = time.time() + matrix_multiply(A, B) + end_time = time.time() + print(f"Обычное умножение: {end_time - start_time:.4f} секунд") + + start_time = time.time() + parallel_matrix_multiply(A, B, num_threads) + end_time = time.time() + print(f"Параллельное умножение: {end_time - start_time:.4f} секунд") + +def test_matrix_multiply(): + A = [ + [1, 2], + [3, 4] + ] + B = [ + [5, 6], + [7, 8] + ] + expected_result = [ + [19, 22], + [43, 50] + ] + result = matrix_multiply(A, B) + assert result == expected_result, f"Тест не пройден! Результат: {result}" + + try: + A = [ + [1, 2] + ] + B = [ + [5, 6], + [7, 8] + ] + matrix_multiply(A, B) + except ValueError: + print("Ошибка умножения матриц с несовпадающими размерами (ожидаемо).") + +if __name__ == "__main__": + print("Запуск тестов...") + test_matrix_multiply() + print("Тесты пройдены успешно!") + + print("\nЗапуск бенчмаркинга...") + benchmark_matrix_multiplication() \ No newline at end of file