From 4ab74fbd5733f4ed832056e0aa7160b3a667e96b Mon Sep 17 00:00:00 2001 From: mochalov danila Date: Wed, 6 Nov 2024 02:56:57 +0400 Subject: [PATCH] mochalov_danila_lab_5_is_ready --- mochalov_danila_lab_5/main.py | 89 +++++++++++++++++++++++++++++++++ mochalov_danila_lab_5/readme.md | 34 +++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 mochalov_danila_lab_5/main.py create mode 100644 mochalov_danila_lab_5/readme.md diff --git a/mochalov_danila_lab_5/main.py b/mochalov_danila_lab_5/main.py new file mode 100644 index 0000000..e1ca3e7 --- /dev/null +++ b/mochalov_danila_lab_5/main.py @@ -0,0 +1,89 @@ +import random as rnd +import time +from multiprocessing import Pool + +# Инициализируем матрицу результата нулями (так легче!) +base_matrix = [[0 for i in range(500)] for j in range(500)] + +# Функция для генерации квадратной матрицы заданного размера со случайными значениями от 0 до 100 +def generateMatrixWithSize(size): + return [[rnd.randint(0, 100) for i in range(size)] for j in range(size)] + +# Функция для вывода матрицы на экран +def printMatrix(matrix): + for row in matrix: + print(*row, sep="\t") + +# Функция для перемножения матриц без использования потоков (стандартный алгоритм) +def multiplyMatrixOGWay(matrix1, matrix2): + l1 = len(matrix1) + l2 = len(matrix2) + global base_matrix # Используем глобальную переменную для хранения результата + result = base_matrix + for i in range(l1): + for j in range(l2): + for k in range(l2): + result[i][j] += matrix1[i][k] * matrix2[k][j] + + return result + + +# Функция для перемножения части матриц в отдельном процессе (worker для Pool) +def matrixMultiplyByOneProcess(args): + matrix1_slice, matrix2, start_i, end_i = args # Распаковываем аргументы + global base_matrix # Используем глобальную переменную для хранения результата + + # Локальная ссылка для удобства + result = base_matrix + + for i in range(end_i-start_i): + for j in range(len(matrix2[0])): + for k in range(len(matrix2)): + result[i + start_i][j] += matrix1_slice[i][k] * matrix2[k][j] + + +# Функция для параллельного перемножения матриц с использованием процессов +def matrixMultiplyWithProcesses(matrix1, matrix2, process_count): + l1 = len(matrix1) + + # Расчет количества строк на каждый процесс + chunk_size = l1 // process_count + remainder = l1 % process_count + + args = [] + start_i = 0 + for i in range(process_count): + end_i = start_i + chunk_size + (1 if i < remainder else 0) + args.append((matrix1[start_i:end_i], matrix2, start_i, end_i)) + start_i = end_i + + # Создание пула процессов и выполнение расчета + with Pool(processes=process_count) as pool: + pool.map(matrixMultiplyByOneProcess, args) + + +if __name__ == "__main__": + + matrix_sizes = [100, 300, 500] + num_processes = [1, 5, 10] + + for size in matrix_sizes: + matrix1 = generateMatrixWithSize(size) + matrix2 = generateMatrixWithSize(size) + + # Замер времени для стандартного умножения + base_matrix = [[0 for i in range(size)] for j in range(size)] # Очищаем перед каждым запуском. + start_time = time.time() + multiplyMatrixOGWay(matrix1, matrix2) + end_time = time.time() + print(f"Обычный режим. Размер матрицы: {size}. {end_time - start_time} сек.") + + # Замер времени для параллельного умножения с разным количеством процессов + for processes in num_processes: + base_matrix = [[0 for i in range(size)] for j in range(size)] # Очищаем перед каждым запуском. + start_time = time.time() + matrixMultiplyWithProcesses(matrix1, matrix2, processes) + end_time = time.time() + print(f"Параллельный режим. Размер матрицы: {size}. Количество процессов: {processes}. {end_time - start_time} сек.") + + print("\n\n") \ No newline at end of file diff --git a/mochalov_danila_lab_5/readme.md b/mochalov_danila_lab_5/readme.md new file mode 100644 index 0000000..2d97b90 --- /dev/null +++ b/mochalov_danila_lab_5/readme.md @@ -0,0 +1,34 @@ +# Лабораторная работа №2 +#### ПИбд-42. Мочалов Данила. + +#### Выполнение +Были реализованы два алгоритма для перемножения матриц: обычный и паралелльный. Параллельный алгоритм использует multiprocessing.Pool для разделения вычислений между несколькими процессами. + +#### Результаты бенчмарков: + +Были проведены тесты для матриц размером 100x100, 300x300 и 500x500 элементов с разным количеством процессов (1, 5, 10). Результаты представлены в таблице: + +| Размер матрицы | Алгоритм | Кол-во процессов |Время (сек.)| +|----------------|------------|------------------|------------| +| 100x100 |Обычный |- |0.21 | +| 100x100 |Параллельный|1 |0.59 | +| 100x100 |Параллельный|5 |0.34 | +| 100x100 |Параллельный|10 |0.32 | +| 300x300 |Обычный |- |6.59 | +| 300x300 |Параллельный|1 |7.03 | +| 300x300 |Параллельный|5 |2.00 | +| 300x300 |Параллельный|10 |1.54 | +| 500x500 |Обычный |- |29.81 | +| 500x500 |Параллельный|1 |33.83 | +| 500x500 |Параллельный|5 |8.57 | +| 500x500 |Параллельный|10 |5.67 | +--------------------------------------------------------------- +#### Анализ +- Для маленьких матриц (100x100) параллельный алгоритм с одним процессом работает медленнее последовательного. Это связано с накладными расходами на создание и управление процессом, которые превышают выигрыш от параллелизма. + +- С увеличением размера матрицы эффективность параллельного алгоритма возрастает. Для матриц 300x300 и 500x500 наблюдается значительное ускорение по сравнению с последовательным алгоритмом. + +- Количество процессов, обеспечивающее максимальное ускорение, зависит от размера матрицы и аппаратных возможностей системы. В данном случае, для матрицы 300x300 использование 10 процессов дает лучший результат, а для 500x500 - тоже 10. Дальнейшее увеличение количества процессов может привести к снижению производительности из-за увеличения накладных расходов на межпроцессное взаимодействие. + +#### Демонстрация +[Доступна по ссылке](https://drive.google.com/file/d/1GxPw9syJVnxb65zP6uQVNYyLjZ-HrfOo/view?usp=sharing) \ No newline at end of file