Merge pull request '[Л/Р 5] Плаксина Александра' (#93) from Sanechka_Plaksina/distributed-computing:plaksina-av-lab-5 into main

Reviewed-on: http://student.git.athene.tech/v.moiseev/distributed-computing/pulls/93
This commit is contained in:
Vladislav Moiseev 2023-12-17 23:39:50 +04:00
commit 21bb9f5e7b
13 changed files with 298 additions and 0 deletions

View File

@ -0,0 +1,100 @@
# Отчет по лабораторной работе №5
Выполнила студентка гр. ИСЭбд-41 Плаксина А.В.
# Описание работы приложения
Приложение реализовнао на языке питон, использована среда PyCharm для разработки.
Было развернуто два приложения:
1. Веб приложение для умножения матриц
2. Консольное приложение для бенчмаркинга
Последовательно запускаем две программы: сначала simple_app.py, затем benchmark.py.
Веб - приложение позволяет указать размеры матрицы и используемый алгоритм, и на основании этого получить результат перемножения матриц в интерактивном режиме
Развернули два приложения
1. Приложение 1 - веб приложение для умножения матриц
2. Приложение 2 - консольное приложение для сравнения эффективности работы алгоритмов.
Первое приложение дает нам возможность умножить матрицы, получить результат в интерактивном режиме
с указанием используемого алгоритма и с указанием размера матрицы.
При запуске веб приложения с выбором последовательного умножения:
![](photo/ph23.jpg)
Результат последовательного умножения:
![](photo/ph24.jpg)
Код реализующий последовательное умножение матриц:
```cs
def multiply_matrices(matrix_a, matrix_b):
if len(matrix_a[0]) != len(matrix_b):
raise ValueError("матрицы имеют разную длину")
result = [[0 for _ in range(len(matrix_b[0]))] for _ in range(len(matrix_a))]
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
```
При запуске веб приложения с выбором параллельного умножения:
![](photo/ph25.jpg)
Результат параллельного умножения:
![](photo/ph26.jpg)
Код реализующий параллельное умножение матриц:
```cs
def multiply_matrices_parallel(matrix_a, matrix_b, threads):
if len(matrix_a[0]) != len(matrix_b):
raise ValueError("матрицы имеют разную длину")
result = [[0 for _ in range(len(matrix_b[0]))] for _ in range(len(matrix_a))]
with multiprocessing.Pool(processes=threads) as pool:
args_list = [(matrix_a, matrix_b, i) for i in range(len(matrix_a))]
rows_results = pool.map(multiply_row, args_list)
for row_result, row_index in rows_results:
result[row_index] = row_result
return result
```
# Бенчмаркинг
Для сравнения времени работы двух алгоритмов умножения, проведем несколько бенчмарков
Для матриц размерностью 100x100, 300x300, 500x500, для параллельного алгоритма дополнительно для каждого введенного количества потоков (4, 16, 32)
Результаты бенчмаркинга для последовательного способа матриц различной размерности:
![](photo/ph27.jpg)
Результаты бенчмаркинга для параллельного способа матриц различной размерности с количеством потоков равном 4:
![](photo/ph28.jpg)
Результаты бенчмаркинга для параллельного способа матриц различной размерности с количеством потоков равном 16:
![](photo/ph29.jpg)
Результаты бенчмаркинга для параллельного способа матриц различной размерности с количеством потоков равном 32:
![](photo/ph30.jpg)
# Вывод
С использованием параллельного алгоритма скорость обработки существенно увеличивается, особенно при большой размерности матрицы.
В данном примере оптимальная скорость достигается при количестве потоков равном 16.

View File

@ -0,0 +1,82 @@
import multiprocessing
import numpy as np
import time
def multiply_matrices(matrix_a, matrix_b):
if len(matrix_a[0]) != len(matrix_b):
raise ValueError("матрицы имеют разную длину")
result = [[0 for _ in range(len(matrix_b[0]))] for _ in range(len(matrix_a))]
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 multiply_row(args):
matrix_a, matrix_b, i = args
row_result = [0 for _ in range(len(matrix_b[0]))]
for j in range(len(matrix_b[0])):
for k in range(len(matrix_b)):
row_result[j] += matrix_a[i][k] * matrix_b[k][j]
return row_result, i
def multiply_matrices_parallel(matrix_a, matrix_b, threads):
if len(matrix_a[0]) != len(matrix_b):
raise ValueError("матрицы имеют разную длину")
result = [[0 for _ in range(len(matrix_b[0]))] for _ in range(len(matrix_a))]
with multiprocessing.Pool(processes=threads) as pool:
args_list = [(matrix_a, matrix_b, i) for i in range(len(matrix_a))]
rows_results = pool.map(multiply_row, args_list)
for row_result, row_index in rows_results:
result[row_index] = row_result
return result
def benchmark_sequential(size):
matrix_a = np.random.rand(size, size)
matrix_b = np.random.rand(size, size)
start_time = time.time()
multiply_matrices(matrix_a, matrix_b)
end_time = time.time()
return end_time - start_time
def benchmark_parallel(size, num_threads):
matrix_a = np.random.rand(size, size)
matrix_b = np.random.rand(size, size)
start_time = time.time()
multiply_matrices_parallel(matrix_a, matrix_b, num_threads)
end_time = time.time()
return end_time - start_time
if __name__ == "__main__":
sizes = [100, 300, 500]
threads = [4, 16, 32]
for size in sizes:
sequential_time = benchmark_sequential(size)
print(f"Время для последовательного способа: {sequential_time} с")
print(f"Размер матрицы: {size}x{size}")
for thread in threads:
for size in sizes:
parallel_time = benchmark_parallel(size, thread)
print(f"Размер матрицы: {size}x{size}")
print(f"Время для параллельного спобсоба: {parallel_time} с")
print(f"Потоков: {thread}")

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Умножение матриц</title>
</head>
<body>
<h1>Умножение матриц</h1>
<form action="/multiply" method="post">
<label for="matrix_a">Размер матриц:</label>
<input type="text" name="matrix_a" required><br>
<label for="operation_type">Способ умножения:</label>
<select name="operation_type">
<option value="sequential">Последовательно</option>
<option value="parallel">Параллельно</option>
</select><br>
<button type="submit">Умножение матриц</button>
</form>
</body>
</html>

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Результат</title>
</head>
<body>
<h1>Результат</h1>
<p>Матрица A:</p>
<pre>{{ matrix_a }}</pre>
<p>Матрица B:</p>
<pre>{{ matrix_b }}</pre>
<p>Результат:</p>
<pre>{{ result }}</pre>
<a href="/">Назад</a>
</body>
</html>

View File

@ -0,0 +1,73 @@
import multiprocessing
from flask import Flask, render_template, request
import numpy as np
import concurrent.futures
app = Flask(__name__)
def multiply_matrices(matrix_a, matrix_b):
if len(matrix_a[0]) != len(matrix_b):
raise ValueError("матрицы имеют разную длину")
result = [[0 for _ in range(len(matrix_b[0]))] for _ in range(len(matrix_a))]
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 multiply_row(args):
matrix_a, matrix_b, i = args
row_result = [0 for _ in range(len(matrix_b[0]))]
for j in range(len(matrix_b[0])):
for k in range(len(matrix_b)):
row_result[j] += matrix_a[i][k] * matrix_b[k][j]
return row_result, i
def multiply_matrices_parallel(matrix_a, matrix_b, threads):
if len(matrix_a[0]) != len(matrix_b):
raise ValueError("матрицы имеют разную длину")
result = [[0 for _ in range(len(matrix_b[0]))] for _ in range(len(matrix_a))]
with multiprocessing.Pool(processes=threads) as pool:
args_list = [(matrix_a, matrix_b, i) for i in range(len(matrix_a))]
rows_results = pool.map(multiply_row, args_list)
for row_result, row_index in rows_results:
result[row_index] = row_result
return result
@app.route('/')
def index():
return render_template('index.html')
@app.route('/multiply', methods=['POST'])
def multiply():
n = int(request.form.get('matrix_a'))
matrix_a = np.random.randint(10, size=(n, n))
matrix_b = np.random.randint(10, size=(n, n))
operation_type = request.form.get('operation_type')
if operation_type == 'sequential':
result = multiply_matrices(matrix_a, matrix_b)
elif operation_type == 'parallel':
result = multiply_matrices_parallel(matrix_a, matrix_b, 16)
else:
return "Invalid operation type"
return render_template('result.html', matrix_a=matrix_a, matrix_b=matrix_b, result=result)
if __name__ == '__main__':
app.run(debug=True)