diff --git a/artamonova_tatyana_lab_5/README.md b/artamonova_tatyana_lab_5/README.md new file mode 100644 index 0000000..a796aa2 --- /dev/null +++ b/artamonova_tatyana_lab_5/README.md @@ -0,0 +1,36 @@ + +# Лабораторная работа №5 ПИбд-42 Артамоновой Татьяны + +## Запуск лабораторной работы + +1. Установить библиотеки Python и NumPy +3. Запустить скрипт matrix.py с помощью команды: *python matrix.py* + +## Используемые технологии + +- Язык программирования: Python +- Библиотеки: + * numpy: Для работы с массивами и матрицами + * multiprocessing: Для параллельного выполнения кода + * time: Для измерения времени выполнения + +## Задание на лабораторную работу + +**Кратко:** реализовать умножение двух больших квадратных матриц. + +**Подробно:** в лабораторной работе требуется сделать два алгоритма: обычный и параллельный (задание со * - +реализовать это в рамках одного алгоритма). В параллельном алгоритме предусмотреть ручное задание количества +потоков (число потоков = 1 как раз и реализует задание со *), каждый из которых будет выполнять умножение +элементов матрицы в рамках своей зоны ответственности. + +## Результаты + +![Результат работы](images/results.png) + +## Вывод + +Результаты показывают, что для маленьких матриц последовательное умножение быстрее. +Оптимальное количество потоков близко к количеству ядер процессора. Увеличение количества потоков сверх +оптимального значения не всегда ускоряет вычисления. Параллелизм эффективнее для больших матриц. + +### [Видео](https://vk.com/video212084908_456239362) diff --git a/artamonova_tatyana_lab_5/images/results.png b/artamonova_tatyana_lab_5/images/results.png new file mode 100644 index 0000000..e7cc764 Binary files /dev/null and b/artamonova_tatyana_lab_5/images/results.png differ diff --git a/artamonova_tatyana_lab_5/matrix.py b/artamonova_tatyana_lab_5/matrix.py new file mode 100644 index 0000000..b8420d5 --- /dev/null +++ b/artamonova_tatyana_lab_5/matrix.py @@ -0,0 +1,93 @@ +import time +import multiprocessing +import numpy as np + +def multiply_matrices_sequential(matrix1, matrix2): + rows1 = len(matrix1) + cols1 = len(matrix1[0]) + rows2 = len(matrix2) + cols2 = len(matrix2[0]) + + if cols1 != rows2: + raise ValueError("Число столбцов первой матрицы должно быть равно числу строк второй матрицы.") + + result = [[0 for _ in range(cols2)] for _ in range(rows1)] + for i in range(rows1): + for j in range(cols2): + for k in range(cols1): + result[i][j] += matrix1[i][k] * matrix2[k][j] + return result + +def multiply_matrices_parallel(matrix1, matrix2, num_processes): + rows1 = len(matrix1) + cols1 = len(matrix1[0]) + rows2 = len(matrix2) + cols2 = len(matrix2[0]) + + if cols1 != rows2: + raise ValueError("Число столбцов первой матрицы должно быть равно числу строк второй матрицы.") + + chunk_size = rows1 // num_processes + processes = [] + results = [] + + with multiprocessing.Pool(processes=num_processes) as pool: + for i in range(num_processes): + start_row = i * chunk_size + end_row = (i + 1) * chunk_size if i < num_processes - 1 else rows1 + p = pool.apply_async(multiply_matrix_chunk, (matrix1, matrix2, start_row, end_row)) + processes.append(p) + + for p in processes: + results.append(p.get()) + + result = [[0 for _ in range(cols2)] for _ in range(rows1)] + row_index = 0 + for sub_result in results: + for row in sub_result: + result[row_index] = row + row_index += 1 + + return result + + +def multiply_matrix_chunk(matrix1, matrix2, start_row, end_row): + rows2 = len(matrix2) + cols2 = len(matrix2[0]) + cols1 = len(matrix1[0]) + result = [[0 for _ in range(cols2)] for _ in range(end_row - start_row)] + for i in range(end_row - start_row): + for j in range(cols2): + for k in range(cols1): + result[i][j] += matrix1[i + start_row][k] * matrix2[k][j] + return result + + +def benchmark(matrix_size, num_processes): + matrix1 = np.random.rand(matrix_size, matrix_size).tolist() + matrix2 = np.random.rand(matrix_size, matrix_size).tolist() + + try: + start_time = time.time() + sequential_result = multiply_matrices_sequential(matrix1, matrix2) + end_time = time.time() + sequential_time = end_time - start_time + + start_time = time.time() + parallel_result = multiply_matrices_parallel(matrix1, matrix2, num_processes) + end_time = time.time() + parallel_time = end_time - start_time + return sequential_time, parallel_time + except ValueError as e: + print(f"Ошибка бенчмарка с размером матрицы {matrix_size} и {num_processes} процессов: {e}") + return float('inf'), float('inf') + + +if __name__ == "__main__": + sizes = [100, 300, 500] + num_processes = int(input("Введите количество потоков: ")) + print("Размер | Последовательно | Параллельно") + + for size in sizes: + sequential_time, parallel_time = benchmark(size, num_processes) + print(f"{size:6} | {sequential_time:.4f} с \t | {parallel_time:.4f} с")