Merge pull request 'vaksman_valeria_lab_6' (#91) from vaksman_valeria_lab_6 into main
Reviewed-on: #91
This commit is contained in:
commit
9c6ef7e89e
37
vaksman_valeria_lab_6/README.md
Normal file
37
vaksman_valeria_lab_6/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Лабораторная работа 6. Определение детерминанта матрицы с помощью параллельных вычислений
|
||||||
|
|
||||||
|
## Задание
|
||||||
|
|
||||||
|
Требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять нахождение отдельной группы множителей.
|
||||||
|
|
||||||
|
### Запуск программы
|
||||||
|
|
||||||
|
Для запуска программы необходимо с помощью командной строки в корневой директории файлов прокета прописать:
|
||||||
|
```
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Описание работы программы
|
||||||
|
|
||||||
|
Программа реализует вычисление детерминанта квадратной матрицы с использованием двух алгоритмов: *обычного и параллельного*.
|
||||||
|
|
||||||
|
1. Обычный алгоритм
|
||||||
|
|
||||||
|
Использует функцию ```parallel_det``` для вычисления детерминанта.
|
||||||
|
|
||||||
|
2. Параллельный алгоритм
|
||||||
|
|
||||||
|
Разбивает матрицу на части и использует несколько потоков для параллельного вычисления детерминанта. Количество потоков задается вручную. Реализован с использованием библиотеки ```concurrent.futures```.
|
||||||
|
|
||||||
|
Для каждого размера матрицы программа выводит время выполнения обычного и параллельного алгоритмов, а также соответствующие значения детерминантов.
|
||||||
|
|
||||||
|
### Результат работы программы:
|
||||||
|
|
||||||
|
![](result.png "")
|
||||||
|
|
||||||
|
#### Вывод
|
||||||
|
|
||||||
|
Параллельное выполнение нахождения детерминанта может привести к ускорению, особенно на больших матрицах. Однако, для некоторых матриц, результаты детерминантов могут отличаться между обычным и параллельным выполнением.
|
||||||
|
|
||||||
|
# ВК
|
||||||
|
https://vk.com/video256017065_456239876
|
9
vaksman_valeria_lab_6/docker-compose.yml
Normal file
9
vaksman_valeria_lab_6/docker-compose.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
services:
|
||||||
|
|
||||||
|
project:
|
||||||
|
container_name: project
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./project/Dockerfile
|
||||||
|
expose:
|
||||||
|
- 8008
|
11
vaksman_valeria_lab_6/project/Dockerfile
Normal file
11
vaksman_valeria_lab_6/project/Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Использую базовый образ Python
|
||||||
|
FROM python:3.10-slim
|
||||||
|
|
||||||
|
# Устанавливаю рабочую директорию внутри контейнера
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Копирую исполняемый файл
|
||||||
|
COPY project/main.py .
|
||||||
|
|
||||||
|
# Команда для запуска Python-скрипта
|
||||||
|
CMD ["python", "main.py"]
|
208
vaksman_valeria_lab_6/project/main.py
Normal file
208
vaksman_valeria_lab_6/project/main.py
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
import random
|
||||||
|
import time
|
||||||
|
import copy
|
||||||
|
from multiprocessing import Pool
|
||||||
|
import concurrent.futures
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
|
||||||
|
class Matrix:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.matrix_100 = [[0] * 100 for _ in range(100)]
|
||||||
|
self.matrix_300 = [[0] * 300 for _ in range(300)]
|
||||||
|
self.matrix_500 = [[0] * 500 for _ in range(500)]
|
||||||
|
|
||||||
|
def str_matrix(self, type_list: str):
|
||||||
|
_str = ""
|
||||||
|
|
||||||
|
current_matrix = getattr(self, type_list)
|
||||||
|
|
||||||
|
for i in range(len(current_matrix)):
|
||||||
|
_str += "[ "
|
||||||
|
|
||||||
|
for j in range(len(current_matrix[0])):
|
||||||
|
_str += str(current_matrix[i][j]) + " "
|
||||||
|
|
||||||
|
_str += " ]\n"
|
||||||
|
|
||||||
|
return _str
|
||||||
|
|
||||||
|
# Глобальный объект класса для хранения результата работы потоков
|
||||||
|
result_matrix = copy.deepcopy(Matrix())
|
||||||
|
|
||||||
|
def init_matrix(matrix: Matrix, size: int):
|
||||||
|
support_list_main = []
|
||||||
|
|
||||||
|
for i in range(size):
|
||||||
|
support_list_column = []
|
||||||
|
|
||||||
|
for j in range(size):
|
||||||
|
support_list_column.append(random.randint(0, 5))
|
||||||
|
|
||||||
|
support_list_main.append(support_list_column)
|
||||||
|
|
||||||
|
if size == 100:
|
||||||
|
matrix.matrix_100 = support_list_main
|
||||||
|
elif size == 300:
|
||||||
|
matrix.matrix_300 = support_list_main
|
||||||
|
elif size == 500:
|
||||||
|
matrix.matrix_500 = support_list_main
|
||||||
|
|
||||||
|
# Функция параллельной обработки строк
|
||||||
|
def process_row(args):
|
||||||
|
i, j, m, n = args
|
||||||
|
|
||||||
|
factor = m[j][i] / m[i][i]
|
||||||
|
|
||||||
|
for k in range(i, n):
|
||||||
|
m[j][k] -= factor * m[i][k]
|
||||||
|
|
||||||
|
return m[j]
|
||||||
|
|
||||||
|
def parallel_det(matrix, num_threads=1):
|
||||||
|
n = len(matrix)
|
||||||
|
|
||||||
|
# Создаем копию матрицы, чтобы не изменять исходную
|
||||||
|
m = deepcopy(matrix)
|
||||||
|
|
||||||
|
det_value = 1
|
||||||
|
|
||||||
|
# Функция для параллельной обработки строк
|
||||||
|
def process_row(i, j):
|
||||||
|
factor = m[j][i] / m[i][i]
|
||||||
|
for k in range(i, n):
|
||||||
|
m[j][k] -= factor * m[i][k]
|
||||||
|
|
||||||
|
for i in range(n):
|
||||||
|
# Поиск ненулевого элемента в текущем столбце для обмена строк
|
||||||
|
if m[i][i] == 0:
|
||||||
|
for j in range(i + 1, n):
|
||||||
|
if m[j][i] != 0:
|
||||||
|
m[i], m[j] = m[j], m[i]
|
||||||
|
|
||||||
|
# Меняем знак определителя при обмене строк
|
||||||
|
det_value *= -1
|
||||||
|
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# Если все элементы в столбце равны 0, то определитель равен 0
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Приведение матрицы к треугольному виду с использованием потоков
|
||||||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
|
||||||
|
# Параллельно обрабатываем строки ниже текущей (от i+1 до n)
|
||||||
|
futures = [
|
||||||
|
executor.submit(process_row, i, j) for j in range(i + 1, n)
|
||||||
|
]
|
||||||
|
concurrent.futures.wait(futures)
|
||||||
|
|
||||||
|
# Умножаем на диагональный элемент
|
||||||
|
det_value *= m[i][i]
|
||||||
|
|
||||||
|
return det_value
|
||||||
|
|
||||||
|
def det(matrix):
|
||||||
|
n = len(matrix)
|
||||||
|
# копия матрицы для сохранения исходной
|
||||||
|
m = [row[:] for row in matrix]
|
||||||
|
det_value = 1
|
||||||
|
|
||||||
|
for i in range(n):
|
||||||
|
# Поиск ненулевого элемента в текущем столбце для обмена строк
|
||||||
|
if m[i][i] == 0:
|
||||||
|
for j in range(i + 1, n):
|
||||||
|
if m[j][i] != 0:
|
||||||
|
m[i], m[j] = m[j], m[i]
|
||||||
|
|
||||||
|
# Меняем знак определителя при обмене строк
|
||||||
|
det_value *= -1
|
||||||
|
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return 0 # Если все элементы в столбце равны 0, то определитель равен 0
|
||||||
|
|
||||||
|
# Приведение матрицы к треугольному виду
|
||||||
|
for j in range(i + 1, n):
|
||||||
|
factor = m[j][i] / m[i][i]
|
||||||
|
|
||||||
|
for k in range(i, n):
|
||||||
|
m[j][k] -= factor * m[i][k]
|
||||||
|
|
||||||
|
# Умножаем на диагональный элемент
|
||||||
|
det_value *= m[i][i]
|
||||||
|
|
||||||
|
return det_value
|
||||||
|
|
||||||
|
def run_program():
|
||||||
|
matrix = Matrix()
|
||||||
|
init_matrix(matrix, 100)
|
||||||
|
init_matrix(matrix, 300)
|
||||||
|
init_matrix(matrix, 500)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"100x100:{det(matrix.matrix_100)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 100x100: ", end_time - start_time)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"100x100:{parallel_det(matrix.matrix_100, 3)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 100x100: ", end_time - start_time)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"100x100:{parallel_det(matrix.matrix_100, 5)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 100x100: ", end_time - start_time)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"100x100:{parallel_det(matrix.matrix_100, 8)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 100x100: ", end_time - start_time)
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------------------------------
|
||||||
|
print("\n" + "-" * 50 + "\n")
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"300x300:{det(matrix.matrix_300)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 300x300: ", end_time - start_time)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"300x300:{parallel_det(matrix.matrix_300, 3)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 300x300: ", end_time - start_time)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"300x300:{parallel_det(matrix.matrix_300, 5)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 300x300: ", end_time - start_time)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"300x300:{parallel_det(matrix.matrix_300, 8)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 300x300: ", end_time - start_time)
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------------------------------
|
||||||
|
print("\n" + "-" * 50 + "\n")
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"500x500:{det(matrix.matrix_500)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 500x500: ", end_time - start_time)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"500x500:{parallel_det(matrix.matrix_500, 3)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 500x500: ", end_time - start_time)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"500x500:{parallel_det(matrix.matrix_500, 5)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 500x500: ", end_time - start_time)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"500x500:{parallel_det(matrix.matrix_500, 8)}")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Time 500x500: ", end_time - start_time)
|
||||||
|
|
||||||
|
run_program()
|
BIN
vaksman_valeria_lab_6/result.png
Normal file
BIN
vaksman_valeria_lab_6/result.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 150 KiB |
Loading…
Reference in New Issue
Block a user