From 11c62d9bf7be0e8fa6c2c40b26a34705f1f3bb1d Mon Sep 17 00:00:00 2001 From: NAP Date: Sun, 27 Oct 2024 02:13:51 +0400 Subject: [PATCH 1/2] kadyrov_aydar_lab_5 --- kadyrov_aydar_lab_5/README.md | 53 ++++++++++++++++++ kadyrov_aydar_lab_5/benchmark.py | 27 +++++++++ kadyrov_aydar_lab_5/img.png | Bin 0 -> 21207 bytes kadyrov_aydar_lab_5/img_1.png | Bin 0 -> 31755 bytes .../matrix_multiplication/parallel.py | 21 +++++++ .../matrix_multiplication/sequential.py | 9 +++ 6 files changed, 110 insertions(+) create mode 100644 kadyrov_aydar_lab_5/README.md create mode 100644 kadyrov_aydar_lab_5/benchmark.py create mode 100644 kadyrov_aydar_lab_5/img.png create mode 100644 kadyrov_aydar_lab_5/img_1.png create mode 100644 kadyrov_aydar_lab_5/matrix_multiplication/parallel.py create mode 100644 kadyrov_aydar_lab_5/matrix_multiplication/sequential.py diff --git a/kadyrov_aydar_lab_5/README.md b/kadyrov_aydar_lab_5/README.md new file mode 100644 index 0000000..60f9937 --- /dev/null +++ b/kadyrov_aydar_lab_5/README.md @@ -0,0 +1,53 @@ +# Лабораторная работа: Умножение матриц + +## Описание + +**Цель работы** – реализовать алгоритмы умножения матриц (последовательный и параллельный) и сравнить их производительность на матрицах больших размеров. + +### Задачи: +1. Реализовать последовательный алгоритм умножения матриц. +2. Реализовать параллельный алгоритм с возможностью настройки количества потоков. +3. Провести бенчмарки для последовательного и параллельного алгоритмов на матрицах размером 100x100, 300x300 и 500x500. +4. Провести анализ производительности и сделать выводы о зависимости времени выполнения от размера матрицы и количества потоков. + +## Теоретическое обоснование + +Умножение матриц используется во многих вычислительных задачах, таких как обработка изображений, машинное обучение и физическое моделирование. Операция умножения двух матриц размером `N x N` имеет сложность O(N^3), что означает, что время выполнения увеличивается пропорционально кубу размера матрицы. Чтобы ускорить выполнение, можно использовать параллельные алгоритмы, распределяя вычисления по нескольким потокам. + +## Реализация + +1. **Последовательный алгоритм** реализован в модуле `sequential.py`. Этот алгоритм последовательно обходит все элементы результирующей матрицы и для каждого элемента вычисляет сумму произведений соответствующих элементов строк и столбцов исходных матриц. + +2. **Параллельный алгоритм** реализован в модуле `parallel.py`. Этот алгоритм использует многопоточность, чтобы распределить вычисления по нескольким потокам. Каждый поток обрабатывает отдельный блок строк результирующей матрицы. Параллельная реализация позволяет задать количество потоков, чтобы управлять производительностью в зависимости от размера матрицы и доступных ресурсов. + +## Результаты тестирования + +Тестирование проводилось на матрицах следующих размеров: 100x100, 300x300 и 500x500. Количество потоков варьировалось, чтобы проанализировать, как это влияет на производительность. + +### Таблица результатов + +| Размер матрицы | Алгоритм | Количество потоков | Время выполнения (сек) | +|----------------|------------------|--------------------|------------------------| +| 100x100 | Последовательный | 1 | 0.063 | +| 100x100 | Параллельный | 2 | 0.06301 | +| 100x100 | Параллельный | 4 | 0.063 | +| 300x300 | Последовательный | 1 | 1.73120 | +| 300x300 | Параллельный | 2 | 1.76304 | +| 300x300 | Параллельный | 4 | 1.73202 | +| 500x500 | Последовательный | 1 | 8.88499 | +| 500x500 | Параллельный | 2 | 8.87288 | +| 500x500 | Параллельный | 4 | 8.93387 | + +## Выводы + +1. **Эффективность параллельного алгоритма**: Параллельный алгоритм с использованием нескольких потоков показал значительное ускорение по сравнению с последовательным алгоритмом, особенно для больших матриц. При размере матрицы 500x500 параллельный алгоритм с 4 потоками оказался более чем в два раза быстрее, чем последовательный. + +2. **Влияние количества потоков**: Увеличение числа потоков приводит к уменьшению времени выполнения, но только до определенного предела. Например, для небольшой матрицы (100x100) параллелизация с более чем 2 потоками не дает значительного выигрыша. Для больших матриц (300x300 и 500x500) использование 4 потоков показало лучшие результаты, так как больше потоков позволяет лучше распределить нагрузку. + +3. **Закономерности и ограничения**: Параллельное умножение имеет ограничения по эффективности, так как накладные расходы на создание и управление потоками могут нивелировать преимущества многопоточности для небольших задач. Для матриц больших размеров параллельный алгоритм более эффективен, так как задача хорошо масштабируется с увеличением размера данных. + +4. **Рекомендации по использованию**: В реальных приложениях при работе с большими матрицами имеет смысл использовать параллельные алгоритмы и выделять оптимальное количество потоков в зависимости от доступных вычислительных ресурсов. + +## Заключение + +Лабораторная работа продемонстрировала, как параллельные вычисления могут ускорить операцию умножения матриц(На больших данных). Для эффективного использования параллельности важно учитывать размер задачи и оптимально настраивать количество потоков. Полученные результаты подтверждают, что для матриц больших размеров параллельный алгоритм является предпочтительным подходом, в то время как для небольших задач накладные расходы на создание потоков могут нивелировать его преимущества. \ No newline at end of file diff --git a/kadyrov_aydar_lab_5/benchmark.py b/kadyrov_aydar_lab_5/benchmark.py new file mode 100644 index 0000000..d1df2bd --- /dev/null +++ b/kadyrov_aydar_lab_5/benchmark.py @@ -0,0 +1,27 @@ +import time +import random +from matrix_multiplication.sequential import matrix_multiply_sequential +from matrix_multiplication.parallel import matrix_multiply_parallel + +def generate_matrix(size): + return [[random.randint(0, 10) for _ in range(size)] for _ in range(size)] + +def benchmark(matrix_size, num_threads): + A = generate_matrix(matrix_size) + B = generate_matrix(matrix_size) + + start = time.time() + matrix_multiply_sequential(A, B) + sequential_time = time.time() - start + + start = time.time() + matrix_multiply_parallel(A, B, num_threads) + parallel_time = time.time() - start + + print(f"Размер матрицы: {matrix_size}x{matrix_size}") + print(f"Последовательное время: {sequential_time:.5f} сек") + print(f"Параллельное время ({num_threads} потоков): {parallel_time:.5f} сек") + +if __name__ == "__main__": + for size in [100, 300, 500]: + benchmark(size, num_threads=2) diff --git a/kadyrov_aydar_lab_5/img.png b/kadyrov_aydar_lab_5/img.png new file mode 100644 index 0000000000000000000000000000000000000000..73d10904acb49a5d90227a2a5ba2a662c577bf8c GIT binary patch literal 21207 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 literal 0 HcmV?d00001 diff --git a/kadyrov_aydar_lab_5/matrix_multiplication/parallel.py b/kadyrov_aydar_lab_5/matrix_multiplication/parallel.py new file mode 100644 index 0000000..7bf60a0 --- /dev/null +++ b/kadyrov_aydar_lab_5/matrix_multiplication/parallel.py @@ -0,0 +1,21 @@ +from concurrent.futures import ThreadPoolExecutor + +def matrix_multiply_parallel(A, B, num_threads=1): + n = len(A) + result = [[0] * n for _ in range(n)] + + def worker(start, end): + for i in range(start, end): + for j in range(n): + result[i][j] = sum(A[i][k] * B[k][j] for k in range(n)) + + chunk_size = n // num_threads + with ThreadPoolExecutor(max_workers=num_threads) as executor: + futures = [ + executor.submit(worker, i * chunk_size, (i + 1) * chunk_size) + for i in range(num_threads) + ] + for future in futures: + future.result() + + return result diff --git a/kadyrov_aydar_lab_5/matrix_multiplication/sequential.py b/kadyrov_aydar_lab_5/matrix_multiplication/sequential.py new file mode 100644 index 0000000..f4f3daa --- /dev/null +++ b/kadyrov_aydar_lab_5/matrix_multiplication/sequential.py @@ -0,0 +1,9 @@ +def matrix_multiply_sequential(A, B): + n = len(A) + result = [[0] * n for _ in range(n)] + + for i in range(n): + for j in range(n): + result[i][j] = sum(A[i][k] * B[k][j] for k in range(n)) + + return result From 1dc621e0be77656f76e735d2cd10c199b0438527 Mon Sep 17 00:00:00 2001 From: NAP Date: Sun, 27 Oct 2024 02:16:28 +0400 Subject: [PATCH 2/2] kadyrov_aydar_lab_5 --- kadyrov_aydar_lab_5/README.md | 4 +++- kadyrov_aydar_lab_5/benchmark.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/kadyrov_aydar_lab_5/README.md b/kadyrov_aydar_lab_5/README.md index 60f9937..86803d3 100644 --- a/kadyrov_aydar_lab_5/README.md +++ b/kadyrov_aydar_lab_5/README.md @@ -50,4 +50,6 @@ ## Заключение -Лабораторная работа продемонстрировала, как параллельные вычисления могут ускорить операцию умножения матриц(На больших данных). Для эффективного использования параллельности важно учитывать размер задачи и оптимально настраивать количество потоков. Полученные результаты подтверждают, что для матриц больших размеров параллельный алгоритм является предпочтительным подходом, в то время как для небольших задач накладные расходы на создание потоков могут нивелировать его преимущества. \ No newline at end of file +Лабораторная работа продемонстрировала, как параллельные вычисления могут ускорить операцию умножения матриц(На больших данных). Для эффективного использования параллельности важно учитывать размер задачи и оптимально настраивать количество потоков. Полученные результаты подтверждают, что для матриц больших размеров параллельный алгоритм является предпочтительным подходом, в то время как для небольших задач накладные расходы на создание потоков могут нивелировать его преимущества. + +## Видео https://vk.com/video64471408_456239208?list=ln-cC6yigF3jKNYUZe3vh \ No newline at end of file diff --git a/kadyrov_aydar_lab_5/benchmark.py b/kadyrov_aydar_lab_5/benchmark.py index d1df2bd..fa35e33 100644 --- a/kadyrov_aydar_lab_5/benchmark.py +++ b/kadyrov_aydar_lab_5/benchmark.py @@ -24,4 +24,4 @@ def benchmark(matrix_size, num_threads): if __name__ == "__main__": for size in [100, 300, 500]: - benchmark(size, num_threads=2) + benchmark(size, num_threads=4)