turner_ilya_lab_6 #157

Merged
Alexey merged 1 commits from turner_ilya_lab_6 into main 2024-11-28 23:10:54 +04:00
3 changed files with 105 additions and 0 deletions

View File

@ -0,0 +1,21 @@
# Лабораторная работа №6 - Параллельный поиск значения детерминанта матрицы
## ПИбд-42 || Тюрнер Илья
### Цель лабораторной работы
Изучение принципов работы праллельных вычислений, когда они оправданы, а когда нет.
### Описание:
Был реализован механизм для параллельного вычисления детерминанта матриц с возможностью задания потоков, в том числе и 1 (обычное вычисление). Был применен на матрицах размером 9x9, 10x10 и 11x11. Были сделаны замеры времени для каждого вычисления, проведен анализ и сделаны выводы.
### Результаты:
![Изображение 1](./results.png)
### Выводы:
При параллельном поиске детерминанта мы нацелены уменьшить временные затраты за счет увеличения числа потоков. Это действительно дает свои плоды, но есть некоторые нюансы.
Из результатов видно, что для вычисления детерминанта матрицы в одном потоке потребовалось 322 секунды, тогда как в 8 потоках время составило 142 секунды, а это значит, что мы произвели вычисления более чем вдвое быстрее.
При этом при применении такого подхода к малым вычислениям, мы наоборот можем просесть по затратам, т. к. для управления многопоточностью тоже требуются ресурсы, поэтому определять целесообразность разбиения задачи на потоки следует исходя из ее объема.
Следующий момент - это определение оптимального числа потоков, не всегда больше = лучше, ведь на менеджмент новых потоков также придется тратить ресурсы.
### Видео с демонстрацией работы:
Размещено на платформе VK видео
https://vk.com/video303312410_456239082?t=5s

84
turner_ilya_lab_6/main.py Normal file
View File

@ -0,0 +1,84 @@
import random
import time
import multiprocessing
import numpy as np
# Генерация матрицы
def generate_matrix(size):
return [[random.randint(0, 10) for _ in range(size)] for _ in range(size)]
# Вычисление детерминанта матрицы (рекурсивно)
def determinant(matrix):
size = len(matrix)
if size == 2:
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
det = 0
for col in range(size):
submatrix = [row[:col] + row[col+1:] for row in matrix[1:]]
det += ((-1) ** col) * matrix[0][col] * determinant(submatrix)
return det
# Вычисление детерминанта параллельно
def parallel_determinant(matrix, num_processes):
size = len(matrix)
if size <= 2:
return determinant(matrix)
# Разбиение задачи по строкам на несколько потоков
chunk_size = size // num_processes
chunks = []
# Создание задач для потоков
for i in range(num_processes):
start_row = i * chunk_size
end_row = (i + 1) * chunk_size if i < num_processes - 1 else size
chunks.append((matrix[start_row:end_row], i))
with multiprocessing.Pool(processes=num_processes) as pool:
results = pool.starmap(calculate_determinant_chunk, [(matrix, chunk[0], chunk[1]) for chunk in chunks])
det = sum(results)
return det
# Вычисление детерминанта для части матрицы в одном процессе
def calculate_determinant_chunk(matrix, chunk, chunk_index):
size = len(matrix)
det = 0
for row in chunk:
for col in range(size):
submatrix = [r[:col] + r[col+1:] for r in matrix[1:]]
det += ((-1) ** (chunk_index + col)) * matrix[0][col] * determinant(submatrix)
return det
# Замер времени для параллельного вычисления детерминанта
def benchmark(size, num_processes=1):
matrix = generate_matrix(size)
start_time = time.time()
parallel_determinant(matrix, num_processes)
par_time = time.time() - start_time
return par_time
def main():
# Размеры матриц
matrix_sizes = [9, 10, 11]
# Количество потоков
num_processes_list = [1, 2, 4, 6, 8]
# Таблица с бенчмарками
print("-*" * 40)
print(f"{'Количество потоков':<20}{'|9x9 (сек.)':<20}{'|10x10 (сек.)':<20}{'|11x11 (сек.)'}")
print("-*" * 40)
for num_processes in num_processes_list:
row = f"{num_processes:<20}"
for size in matrix_sizes:
par_time = benchmark(size, num_processes)
row += f"|{par_time:.4f}".ljust(20)
print(row)
print("-*" * 40)
if __name__ == "__main__":
main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB