diff --git a/vaksman_valeria_lab_6/README.md b/vaksman_valeria_lab_6/README.md new file mode 100644 index 0000000..eca50b1 --- /dev/null +++ b/vaksman_valeria_lab_6/README.md @@ -0,0 +1,37 @@ +# Лабораторная работа 6. Определение детерминанта матрицы с помощью параллельных вычислений + +## Задание + +Требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять нахождение отдельной группы множителей. + +### Запуск программы + +Для запуска программы необходимо с помощью командной строки в корневой директории файлов прокета прописать: +``` +python main.py +``` + +### Описание работы программы + +Программа реализует вычисление детерминанта квадратной матрицы с использованием двух алгоритмов: *обычного и параллельного*. + +  1. Обычный алгоритм + +      Использует функцию ```parallel_det``` для вычисления детерминанта. + +  2. Параллельный алгоритм + +      Разбивает матрицу на части и использует несколько потоков для параллельного вычисления детерминанта. Количество потоков задается вручную. Реализован с использованием библиотеки ```concurrent.futures```. + +Для каждого размера матрицы программа выводит время выполнения обычного и параллельного алгоритмов, а также соответствующие значения детерминантов. + +### Результат работы программы: + +![](result.png "") + +#### Вывод + +Параллельное выполнение нахождения детерминанта может привести к ускорению, особенно на больших матрицах. Однако, для некоторых матриц, результаты детерминантов могут отличаться между обычным и параллельным выполнением. + +# ВК +https://vk.com/video256017065_456239876 \ No newline at end of file diff --git a/vaksman_valeria_lab_6/docker-compose.yml b/vaksman_valeria_lab_6/docker-compose.yml new file mode 100644 index 0000000..15851d1 --- /dev/null +++ b/vaksman_valeria_lab_6/docker-compose.yml @@ -0,0 +1,9 @@ +services: + + project: + container_name: project + build: + context: . + dockerfile: ./project/Dockerfile + expose: + - 8008 diff --git a/vaksman_valeria_lab_6/project/Dockerfile b/vaksman_valeria_lab_6/project/Dockerfile new file mode 100644 index 0000000..9fd699f --- /dev/null +++ b/vaksman_valeria_lab_6/project/Dockerfile @@ -0,0 +1,11 @@ +# Использую базовый образ Python +FROM python:3.10-slim + +# Устанавливаю рабочую директорию внутри контейнера +WORKDIR /app + +# Копирую исполняемый файл +COPY project/main.py . + +# Команда для запуска Python-скрипта +CMD ["python", "main.py"] \ No newline at end of file diff --git a/vaksman_valeria_lab_6/project/main.py b/vaksman_valeria_lab_6/project/main.py new file mode 100644 index 0000000..82edb48 --- /dev/null +++ b/vaksman_valeria_lab_6/project/main.py @@ -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() \ No newline at end of file diff --git a/vaksman_valeria_lab_6/result.png b/vaksman_valeria_lab_6/result.png new file mode 100644 index 0000000..328642e Binary files /dev/null and b/vaksman_valeria_lab_6/result.png differ