From effeb9b8cdcaf2d18cc08a4a61fffa90a5d0122d Mon Sep 17 00:00:00 2001 From: Kseniy <––ƒ––iputilin201@gmail.com> Date: Mon, 9 Dec 2024 19:55:48 +0400 Subject: [PATCH] kurushina_ksenia_lab_5 --- kurushina_ksenia_lab_5/README.md | 64 +++++++++++++++++++++++++++ kurushina_ksenia_lab_5/img.png | Bin 0 -> 16204 bytes kurushina_ksenia_lab_5/main.py | 29 ++++++++++++ kurushina_ksenia_lab_5/parallel.py | 21 +++++++++ kurushina_ksenia_lab_5/sequential.py | 9 ++++ 5 files changed, 123 insertions(+) create mode 100644 kurushina_ksenia_lab_5/README.md create mode 100644 kurushina_ksenia_lab_5/img.png create mode 100644 kurushina_ksenia_lab_5/main.py create mode 100644 kurushina_ksenia_lab_5/parallel.py create mode 100644 kurushina_ksenia_lab_5/sequential.py diff --git a/kurushina_ksenia_lab_5/README.md b/kurushina_ksenia_lab_5/README.md new file mode 100644 index 0000000..90a6c71 --- /dev/null +++ b/kurushina_ksenia_lab_5/README.md @@ -0,0 +1,64 @@ +# Лабораторная работа: Реализация умножения матриц + +## Краткое описание + +**Цель работы** – разработать и сравнить последовательный и +параллельный алгоритмы умножения матриц, оценив их +производительность на матрицах больших размеров. + +### Основные задачи: +1. Реализовать алгоритм последовательного умножения матриц. +2. Создать параллельный алгоритм с настраиваемым числом потоков. +3. Провести бенчмарки обоих алгоритмов на матрицах размером 100x100, 300x300 и 500x500. +4. Проанализировать результаты и определить влияние размера матрицы и количества потоков на производительность. + +## Теоретическая часть + +Умножение матриц является ключевой операцией во многих областях, включая машинное обучение, +обработку изображений и моделирование физических процессов. Сложность умножения двух матриц размером +`N x N` составляет O(N³), что делает задачу вычислительно затратной. Для ускорения вычислений используется параллелизм, +позволяющий распределить работу между несколькими потоками. + +## Описание реализации + +1. **Последовательный алгоритм** реализован в файле `sequential.py`. Каждый элемент результирующей матрицы вычисляется +2. как сумма произведений соответствующих элементов +3. строки первой матрицы и столбца второй. + +2. **Параллельный алгоритм** описан в модуле `parallel.py`. +3. Для выполнения вычислений используется многопоточность: каждый поток обрабатывает отдельный блок +4. строк результирующей матрицы. Пользователь может задать число потоков для регулирования нагрузки и эффективности работы. + +## Результаты экспериментов + +Тесты проводились на матрицах следующих размеров: 100x100, 300x300 и 500x500. +Для параллельного алгоритма изменялось +число потоков, чтобы оценить их влияние на скорость вычислений. + + +## Анализ результатов + +1. **Эффективность параллелизма**: Параллельный алгоритм показал прирост производительности +для больших матриц. При размере 500x500 с 4 потоками наблюдалось значительное ускорение. + +2. **Число потоков**: Увеличение потоков улучшает производительность только до определённого момента. +Для маленьких матриц (например, 100x100) дополнительная параллелизация может быть неэффективной. + +3. **Ограничения параллелизма**: Накладные расходы на управление потоками +и их синхронизацию уменьшают преимущества многопоточности при малых объёмах данных. + +4. **Рекомендации**: + +Параллельные алгоритмы наиболее эффективны при работе с большими матрицами. +Настройка числа потоков должна учитывать ресурсы системы и размер задачи. + +## Заключение + +Данная работа продемонстрировала эффективность параллельного умножения матриц на больших данных. +Оптимизация параметров параллельного алгоритма позволяет +значительно сократить время выполнения задач, связанных с вычислительной обработкой матриц. + +## Ссылка на видео + +https://cloud.mail.ru/public/tKoW/ZLDNyHam2 + diff --git a/kurushina_ksenia_lab_5/img.png b/kurushina_ksenia_lab_5/img.png new file mode 100644 index 0000000000000000000000000000000000000000..ee5dbc9251b9228d2ccf6bc748a54fc8fae0c434 GIT binary patch literal 16204 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�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