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 0000000..ee5dbc9 Binary files /dev/null and b/kurushina_ksenia_lab_5/img.png differ diff --git a/kurushina_ksenia_lab_5/main.py b/kurushina_ksenia_lab_5/main.py new file mode 100644 index 0000000..cbf28e5 --- /dev/null +++ b/kurushina_ksenia_lab_5/main.py @@ -0,0 +1,29 @@ +import time +import random + +from DAS_2024_1.kurushina_ksenia_lab_5.parallel import matrix_multiply_parallel +from DAS_2024_1.kurushina_ksenia_lab_5.sequential import matrix_multiply_sequential + + +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=4) diff --git a/kurushina_ksenia_lab_5/parallel.py b/kurushina_ksenia_lab_5/parallel.py new file mode 100644 index 0000000..7bf60a0 --- /dev/null +++ b/kurushina_ksenia_lab_5/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/kurushina_ksenia_lab_5/sequential.py b/kurushina_ksenia_lab_5/sequential.py new file mode 100644 index 0000000..f4f3daa --- /dev/null +++ b/kurushina_ksenia_lab_5/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