degtyarev_mikhail_lab_5 is ready #167
81
degtyarev_mikhail_lab_5/README.md
Normal file
81
degtyarev_mikhail_lab_5/README.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# Лабораторная 5
|
||||||
|
## Вариант 9
|
||||||
|
|
||||||
|
## Задание
|
||||||
|
Кратко: реализовать умножение двух больших квадратных матриц.
|
||||||
|
|
||||||
|
Подробно: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять умножение элементов матрицы в рамках своей зоны ответственности.
|
||||||
|
|
||||||
|
## Описание Программы
|
||||||
|
|
||||||
|
### Алгоритмы:
|
||||||
|
|
||||||
|
**Последовательный**
|
||||||
|
|
||||||
|
```
|
||||||
|
def sequential_matrix_multiply(matrix_a, matrix_b):
|
||||||
|
result = np.zeros((len(matrix_a), len(matrix_b[0])))
|
||||||
|
for i in range(len(matrix_a)):
|
||||||
|
for j in range(len(matrix_b[0])):
|
||||||
|
for k in range(len(matrix_b)):
|
||||||
|
result[i][j] += matrix_a[i][k] * matrix_b[k][j]
|
||||||
|
return result
|
||||||
|
```
|
||||||
|
|
||||||
|
**Параллельный**
|
||||||
|
|
||||||
|
```
|
||||||
|
def parallel_matrix_multiply_worker(args):
|
||||||
|
matrix_a, matrix_b, row_start, row_end, result = args
|
||||||
|
local_result = np.zeros((row_end - row_start, len(matrix_b[0])))
|
||||||
|
for i in range(row_start, row_end):
|
||||||
|
for j in range(len(matrix_b[0])):
|
||||||
|
for k in range(len(matrix_b)):
|
||||||
|
local_result[i - row_start][j] += matrix_a[i][k] * matrix_b[k][j]
|
||||||
|
result.extend(local_result)
|
||||||
|
|
||||||
|
|
||||||
|
def parallel_matrix_multiply(matrix_a, matrix_b, num_processes=2):
|
||||||
|
num_rows_a = len(matrix_a)
|
||||||
|
chunk_size = num_rows_a // num_processes
|
||||||
|
processes = []
|
||||||
|
manager = multiprocessing.Manager()
|
||||||
|
result = manager.list()
|
||||||
|
|
||||||
|
for i in range(num_processes):
|
||||||
|
row_start = i * chunk_size
|
||||||
|
row_end = (i + 1) * chunk_size if i < num_processes - 1 else num_rows_a
|
||||||
|
process_args = (matrix_a, matrix_b, row_start, row_end, result)
|
||||||
|
process = multiprocessing.Process(target=parallel_matrix_multiply_worker, args=(process_args,))
|
||||||
|
processes.append(process)
|
||||||
|
|
||||||
|
for process in processes:
|
||||||
|
process.start()
|
||||||
|
|
||||||
|
for process in processes:
|
||||||
|
process.join()
|
||||||
|
|
||||||
|
return np.vstack(result)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Результат:
|
||||||
|
|
||||||
|
Для матриц каждой размерности (100x100, 300x300, 500x500) с разными потоками были выполнены замеры по времени:
|
||||||
|
|
||||||
|
**100x100 2, 4 потока**
|
||||||
|
|
||||||
|
![](screens/img.png)
|
||||||
|
|
||||||
|
**300x300 2, 4 потока**
|
||||||
|
|
||||||
|
![](screens/img_1.png)
|
||||||
|
|
||||||
|
**500x500 2, 4 потока**
|
||||||
|
|
||||||
|
![](screens/img_2.png)
|
||||||
|
|
||||||
|
Из приведенных выше тестов, можно сделать вывод, что матрица размерностью 100x100 выполняется быстрее последовательно.
|
||||||
|
Матрица 300x300 выполняется быстрее последовательно, если 2 потока, если 4 потока - то быстрее параллельно.
|
||||||
|
Матрица 500x500 выполняется быстрее с 2, 4 потоками.
|
||||||
|
|
||||||
|
Ссылка на видео: https://vk.com/video151119348_456239202?list=ln-Zzcz0lPuhOW9ZAUZhK
|
69
degtyarev_mikhail_lab_5/main.py
Normal file
69
degtyarev_mikhail_lab_5/main.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
def sequential_matrix_multiply(matrix_a, matrix_b):
|
||||||
|
result = np.zeros((len(matrix_a), len(matrix_b[0])))
|
||||||
|
for i in range(len(matrix_a)):
|
||||||
|
for j in range(len(matrix_b[0])):
|
||||||
|
for k in range(len(matrix_b)):
|
||||||
|
result[i][j] += matrix_a[i][k] * matrix_b[k][j]
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def parallel_matrix_multiply_worker(args):
|
||||||
|
matrix_a, matrix_b, row_start, row_end, result = args
|
||||||
|
local_result = np.zeros((row_end - row_start, len(matrix_b[0])))
|
||||||
|
for i in range(row_start, row_end):
|
||||||
|
for j in range(len(matrix_b[0])):
|
||||||
|
for k in range(len(matrix_b)):
|
||||||
|
local_result[i - row_start][j] += matrix_a[i][k] * matrix_b[k][j]
|
||||||
|
result.extend(local_result)
|
||||||
|
|
||||||
|
|
||||||
|
def parallel_matrix_multiply(matrix_a, matrix_b, num_processes=2):
|
||||||
|
num_rows_a = len(matrix_a)
|
||||||
|
chunk_size = num_rows_a // num_processes
|
||||||
|
processes = []
|
||||||
|
manager = multiprocessing.Manager()
|
||||||
|
result = manager.list()
|
||||||
|
|
||||||
|
for i in range(num_processes):
|
||||||
|
row_start = i * chunk_size
|
||||||
|
row_end = (i + 1) * chunk_size if i < num_processes - 1 else num_rows_a
|
||||||
|
process_args = (matrix_a, matrix_b, row_start, row_end, result)
|
||||||
|
process = multiprocessing.Process(target=parallel_matrix_multiply_worker, args=(process_args,))
|
||||||
|
processes.append(process)
|
||||||
|
|
||||||
|
for process in processes:
|
||||||
|
process.start()
|
||||||
|
|
||||||
|
for process in processes:
|
||||||
|
process.join()
|
||||||
|
|
||||||
|
return np.vstack(result)
|
||||||
|
|
||||||
|
|
||||||
|
def run_test(matrix_size, num_processes=2):
|
||||||
|
matrix_a = np.random.rand(matrix_size, matrix_size)
|
||||||
|
matrix_b = np.random.rand(matrix_size, matrix_size)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
sequential_matrix_multiply(matrix_a, matrix_b)
|
||||||
|
sequential_time = time.time() - start_time
|
||||||
|
print(f"Время последовательного: ({matrix_size}x{matrix_size}): {sequential_time} с.")
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
parallel_matrix_multiply(matrix_a, matrix_b, num_processes)
|
||||||
|
parallel_time = time.time() - start_time
|
||||||
|
print(
|
||||||
|
f"Время параллельного умножения матриц ({matrix_size}x{matrix_size}) с {num_processes} потоками заняло: {parallel_time} с.")
|
||||||
|
print("========================================")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run_test(100, num_processes=2)
|
||||||
|
run_test(100, num_processes=4)
|
||||||
|
run_test(300, num_processes=2)
|
||||||
|
run_test(300, num_processes=4)
|
||||||
|
run_test(500, num_processes=2)
|
||||||
|
run_test(500, num_processes=4)
|
BIN
degtyarev_mikhail_lab_5/screens/img.png
Normal file
BIN
degtyarev_mikhail_lab_5/screens/img.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
degtyarev_mikhail_lab_5/screens/img_1.png
Normal file
BIN
degtyarev_mikhail_lab_5/screens/img_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
degtyarev_mikhail_lab_5/screens/img_2.png
Normal file
BIN
degtyarev_mikhail_lab_5/screens/img_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Loading…
Reference in New Issue
Block a user