diff --git a/lazarev_andrey_lab_5/README.md b/lazarev_andrey_lab_5/README.md new file mode 100644 index 0000000..e3d54f8 --- /dev/null +++ b/lazarev_andrey_lab_5/README.md @@ -0,0 +1,35 @@ +# Лабораторная работа №5 + +## Задание + +Реализовать последовательное и параллельное умножение матриц размером 100x100, 300x300, 500x500 элементов, сравнить результаты. + +## Описание алгоритмов + +### Последовательное умножение + +- Реализовано при помощи тройного цикла умножения квадратных матриц с сложностью O(n³), т.е. при увеличении размера матриц увеличится и время работы алгоритма. + +### Параллельное умножение + +- Реализовано при помощи разделения матриц на части в зависимости от количества потоков, а после умножаются две прямоугольные матрицы. +- Сложность аналогична последовательному алгоритму, но разделение матриц значительно снижает время работы алгоритма. + +### Умножение с использованием библиотеки Numpy + +- Умножение с ипользованием библиотеки Numpy максимально отпимизировано за счет кэшированияи и использования библиотеки BLAS (Basic Linear Algebra Subprograms) на языке C для выполнения линейной алгребры. + +## Результаты + +![](report.png "") + + +### Вывод +- Параллельное умножение матриц эффективно при работе с большими матрицами при увеличении потоков. +- Последовательное умножение матриц эффективно использовать при меньших размерах матриц, где выйгрыш от управления потоками минимален. +- Numpy показал блестящий результат. + +## Видеодемонстрация работоспособности + +[Демонстрация работы сервисов](https://files.ulstu.ru/s/4jmPMLK3szdKdWS) + diff --git a/lazarev_andrey_lab_5/main.py b/lazarev_andrey_lab_5/main.py new file mode 100644 index 0000000..433bcba --- /dev/null +++ b/lazarev_andrey_lab_5/main.py @@ -0,0 +1,81 @@ +import numpy as np +from concurrent.futures import ProcessPoolExecutor +import time + +#Функция умножения матриц +def multi(A, B): + n = len(A) + k = len(B) + C = np.zeros((n, n)) + + for i in range(n): + for j in range(n): + C[i][j] = sum(A[i][p] * B[p][j] for p in range(k)) + + return C + +# Функция последовательного умножения матриц +def multi_sequential(A, B): + n = len(A) + C = np.zeros((n, n)) + for i in range(n): + for k in range(n): + temp = A[i][k] + for j in range(n): + C[i][j] += temp * B[k][j] + return C + +# Функция умножения матриц с numpy +def multi_numpy(A, B): + return np.dot(A, B) + +# Параллельное умножение матриц +def multi_parallel(A, B, num_threads): + n = len(A) + C = np.zeros((n, n)) + step = n // num_threads + + with ProcessPoolExecutor(max_workers=num_threads) as executor: + futures = [] + for i in range(num_threads): + start_row = i * step + end_row = (i + 1) * step if i != num_threads - 1 else n + + a_slice = A[:, i*step: (i+1)*step] + b_slice = B[start_row:end_row] + + futures.append(executor.submit(multi, a_slice, b_slice)) + + for future in futures: + C += future.result() + + return C + +# Пример использования +if __name__ == "__main__": + matrix_sizes = [100, 300, 500] + num_threads = [2, 4, 5, 10] + for n in matrix_sizes: + A = np.random.rand(n, n) + B = np.random.rand(n, n) + + # Умножение с numpy + start_np = time.time() + nump = multi_numpy(A, B) + end_np = time.time() + print(f'Умножение матриц {n}x{n} последовательно с numpy: {(end_np - start_np):.6f} с.') + + # Последовательное умножение + start_seq = time.time() + sequential = multi_sequential(A, B) + end_seq = time.time() + print(f'Умножение матриц {n}x{n} последовательно: {(end_seq - start_seq):.6f} с.') + + # Параллельное умножение + for thread in num_threads: + start_par = time.time() + parallel = multi_parallel(A, B, thread) + end_par = time.time() + print(f'Умножение матриц {n}x{n} параллельно для {thread} потоков: {(end_par - start_par):.3f} с.') + + print('') \ No newline at end of file diff --git a/lazarev_andrey_lab_5/report.png b/lazarev_andrey_lab_5/report.png new file mode 100644 index 0000000..9a0667b Binary files /dev/null and b/lazarev_andrey_lab_5/report.png differ