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
100
tasks/plaksina-av/lab_5/README.md
Normal 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.
|
82
tasks/plaksina-av/lab_5/benchmarking.py
Normal 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}")
|
BIN
tasks/plaksina-av/lab_5/photo/ph23.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
tasks/plaksina-av/lab_5/photo/ph24.jpg
Normal file
After Width: | Height: | Size: 138 KiB |
BIN
tasks/plaksina-av/lab_5/photo/ph25.jpg
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tasks/plaksina-av/lab_5/photo/ph26.jpg
Normal file
After Width: | Height: | Size: 91 KiB |
BIN
tasks/plaksina-av/lab_5/photo/ph27.jpg
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
tasks/plaksina-av/lab_5/photo/ph28.jpg
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
tasks/plaksina-av/lab_5/photo/ph29.jpg
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
tasks/plaksina-av/lab_5/photo/ph30.jpg
Normal file
After Width: | Height: | Size: 48 KiB |
24
tasks/plaksina-av/lab_5/templates/index.html
Normal 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>
|
19
tasks/plaksina-av/lab_5/templates/result.html
Normal 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>
|
73
tasks/plaksina-av/lab_5/web.py
Normal 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)
|