Merge pull request 'pupkov_alexey_lab6 is ready' (#198) from pupkov_alexey_lab_6 into main
Reviewed-on: #198
This commit is contained in:
commit
7da1307156
67
pupkov_alexey_lab_6/README.md
Normal file
67
pupkov_alexey_lab_6/README.md
Normal file
@ -0,0 +1,67 @@
|
||||
# Пупков Алексей ИСЭбд-41
|
||||
# Отчет по вычислению детерминанта матрицы
|
||||
## Описание
|
||||
В данной лабораторной работе реализовано вычисление детерминанта квадратной матрицы двумя способами: последовательно и параллельно. Для параллельного вычисления используется библиотека concurrent.futures в Python. Программа позволяет задавать количество процессов, что позволяет наблюдать за изменением производительности при увеличении числа потоков.
|
||||
## Как работает код:
|
||||
|
||||
1. Импорт библиотек
|
||||
- numpy используется для работы с матрицами и для вычислений
|
||||
- concurrent.futures помогает запускать параллельные задачи с использованием потоков
|
||||
- time используется для измерения времени выполнения алгоритмов
|
||||
- argparse для обработки аргументов командной строки
|
||||
|
||||
2. Функция determinant_sequential(matrix)
|
||||
- Вычисляет детерминант матрицы, используя метод Гаусса (прямой ход преобразования матрицы в верхнетреугольную форму)
|
||||
|
||||
3. Функция calculate_minor(matrix, i, j)
|
||||
- Возвращает минор элемента матрицы, находящегося в позиции (i, j)
|
||||
|
||||
4. Функция determinant_parallel(matrix, num_threads)
|
||||
- Рассчитывает детерминант параллельно, распределяя вычисление миноров между потоками
|
||||
|
||||
5. Функция benchmark(matrix_sizes, num_threads_list)
|
||||
- Тестирует и сравнивает скорость последовательного и параллельного алгоритмов для матриц разных размеров
|
||||
|
||||
## Результаты
|
||||
|
||||
Размер матрицы: 100x100
|
||||
Последовательный алгоритм занял: 0.0150 секунд
|
||||
|
||||
Параллельный алгоритм с 1 потоками занял: 0.0170 секунд
|
||||
|
||||
Параллельный алгоритм с 2 потоками занял: 0.0200 секунд
|
||||
|
||||
Параллельный алгоритм с 4 потоками занял: 0.0200 секунд
|
||||
|
||||
Параллельный алгоритм с 8 потоками занял: 0.0200 секунд
|
||||
|
||||
|
||||
Размер матрицы: 300x300
|
||||
Последовательный алгоритм занял: 0.1492 секунд
|
||||
|
||||
Параллельный алгоритм с 1 потоками занял: 0.1510 секунд
|
||||
|
||||
Параллельный алгоритм с 2 потоками занял: 3.1997 секунд
|
||||
|
||||
Параллельный алгоритм с 4 потоками занял: 1.8139 секунд
|
||||
|
||||
Параллельный алгоритм с 8 потоками занял: 1.6556 секунд
|
||||
|
||||
Размер матрицы: 500x500
|
||||
Последовательный алгоритм занял: 0.4196 секунд
|
||||
|
||||
Параллельный алгоритм с 1 потоками занял: 0.4201 секунд
|
||||
|
||||
Параллельный алгоритм с 2 потоками занял: 6.0421 секунд
|
||||
|
||||
Параллельный алгоритм с 4 потоками занял: 8.1776 секунд
|
||||
|
||||
Параллельный алгоритм с 8 потоками занял: 5.3308 секунд
|
||||
|
||||
## Выводы
|
||||
Время параллельного алгоритма (с любым количеством потоков) оказывается немного выше, чем у последовательного. Это объясняется затратами на создание и управление потоками, которые не компенсируются выигрышем от параллельных вычислений для маленьких задач. В случае малых матриц лучше использовать последовательный алгоритм. С увеличением размеров матриц (300x300 и 500x500) время параллельного вычисления увеличивается, что указывает на неэффективность при использовании большого количества процессов.
|
||||
|
||||
## Запуск
|
||||
Python main.py – threads 1 2 4 8
|
||||
|
||||
[Ссылка на демонстрацию работы программы](https://vk.com/video547368103_456239606?list=ln-1NucWuxvOOBqHDCdvn)
|
84
pupkov_alexey_lab_6/main.py
Normal file
84
pupkov_alexey_lab_6/main.py
Normal file
@ -0,0 +1,84 @@
|
||||
import numpy as np
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
import time
|
||||
import argparse
|
||||
|
||||
# Вычисляет детерминант матрицы с использованием метода Гаусса
|
||||
def determinant_sequential(matrix):
|
||||
n = matrix.shape[0]
|
||||
mat = matrix.copy().astype(float)
|
||||
|
||||
for i in range(n):
|
||||
if mat[i, i] == 0:
|
||||
for j in range(i + 1, n):
|
||||
if mat[j, i] != 0:
|
||||
mat[[i, j]] = mat[[j, i]] # Меняем строки
|
||||
break
|
||||
|
||||
for j in range(i + 1, n):
|
||||
factor = mat[j, i] / mat[i, i]
|
||||
mat[j] -= factor * mat[i]
|
||||
|
||||
det = np.prod(np.diag(mat))
|
||||
return det
|
||||
|
||||
# Функция для вычисления минора
|
||||
def calculate_minor(matrix, i, j):
|
||||
minor = np.delete(matrix, i, axis=0)
|
||||
minor = np.delete(minor, j, axis=1)
|
||||
return np.linalg.det(minor)
|
||||
|
||||
# Параллельное вычисление
|
||||
def determinant_parallel(matrix, num_threads):
|
||||
|
||||
if num_threads == 1:
|
||||
return determinant_sequential(matrix)
|
||||
|
||||
n = len(matrix)
|
||||
results = []
|
||||
|
||||
with ThreadPoolExecutor(max_workers=num_threads) as executor:
|
||||
futures = [
|
||||
executor.submit(lambda x: ((-1) ** x) * matrix[0, x] * calculate_minor(matrix, 0, x), i)
|
||||
for i in range(n)
|
||||
]
|
||||
for future in futures:
|
||||
results.append(future.result())
|
||||
|
||||
return sum(results)
|
||||
|
||||
def benchmark(matrix_sizes, num_threads_list):
|
||||
for size in matrix_sizes:
|
||||
matrix = np.random.rand(size, size)
|
||||
print(f"\nРазмер матрицы: {size}x{size}")
|
||||
|
||||
# Бенчмарк для последовательного алгоритма
|
||||
start_time = time.time()
|
||||
det_seq = determinant_sequential(matrix)
|
||||
sequential_time = time.time() - start_time
|
||||
print(f"Последовательный алгоритм занял: {sequential_time:.4f} секунд")
|
||||
|
||||
# Бенчмарк для параллельного алгоритма
|
||||
for num_threads in num_threads_list:
|
||||
start_time = time.time()
|
||||
det_par = determinant_parallel(matrix, num_threads)
|
||||
parallel_time = time.time() - start_time
|
||||
print(f"Параллельный алгоритм с {num_threads} потоками занял: {parallel_time:.4f} секунд")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Запуск бенчмарков для последовательного и параллельного вычисления детерминанта.")
|
||||
parser.add_argument(
|
||||
"--threads",
|
||||
type=int,
|
||||
nargs="+",
|
||||
required=True,
|
||||
help="Список количества потоков для параллельного алгоритма (например, --threads 1 2 4 8)"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# Задание размеров матриц для тестов
|
||||
matrix_sizes = [100, 300, 500]
|
||||
num_threads_list = args.threads # Получаем список потоков из аргументов командной строки
|
||||
|
||||
# Запуск бенчмарка
|
||||
benchmark(matrix_sizes, num_threads_list)
|
Loading…
Reference in New Issue
Block a user