diff --git a/davydov_yuriy_lab_6/README.md b/davydov_yuriy_lab_6/README.md new file mode 100644 index 0000000..6ecacaf --- /dev/null +++ b/davydov_yuriy_lab_6/README.md @@ -0,0 +1,19 @@ +# Лабораторная работа №6 - Параллельный поиск значения детерминанта матрицы + +## ПИбд-42 || Давыдов Юрий + +### Цель лабораторной работы + +Изучение принципов параллельных вычислений, а также определение случаев, когда их использование оправдано, а когда нет. + +Описание: +Был реализован механизм для параллельного вычисления детерминанта матриц с возможностью задания числа потоков, включая использование одного потока (для обычного вычисления). Программа была протестирована на матрицах размером 9x9, 10x10 и 11x11. Были проведены замеры времени для каждого вычисления, проведен анализ результатов и сделаны выводы. + +Выводы: +Параллельный расчет детерминанта направлен на снижение времени вычислений за счет увеличения числа потоков, и это действительно дает положительные результаты, но есть несколько важных нюансов. + +Из полученных данных видно, что для вычисления детерминанта матрицы в одном потоке потребовалось 322 секунды, а в 8 потоках время составило 142 секунды, что означает более чем двукратное сокращение времени выполнения. + +Однако, при применении параллельного подхода к небольшим вычислениям, время может даже увеличиться, поскольку управление многопоточностью также требует ресурсов. Поэтому целесообразность разделения задачи на потоки следует определять в зависимости от объема задачи. + +Еще один важный момент — это поиск оптимального числа потоков. Увеличение их числа не всегда приводит к улучшению результатов, так как на управление дополнительными потоками также будут расходоваться ресурсы. diff --git a/davydov_yuriy_lab_6/main.py b/davydov_yuriy_lab_6/main.py new file mode 100644 index 0000000..4c7787c --- /dev/null +++ b/davydov_yuriy_lab_6/main.py @@ -0,0 +1,83 @@ +import random +import time +import multiprocessing + +# Генерация случайной матрицы +def create_random_matrix(dim): + return [[random.randint(0, 10) for _ in range(dim)] for _ in range(dim)] + +# Рекурсивное вычисление детерминанта матрицы +def compute_determinant(matrix): + size = len(matrix) + if size == 2: + return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0] + + result = 0 + for col in range(size): + submatrix = [row[:col] + row[col+1:] for row in matrix[1:]] + result += ((-1) ** col) * matrix[0][col] * compute_determinant(submatrix) + return result + +# Параллельное вычисление детерминанта матрицы +def parallel_determinant_calculation(matrix, num_workers): + size = len(matrix) + if size <= 2: + return compute_determinant(matrix) + + # Разделение задачи по строкам между процессами + rows_per_worker = size // num_workers + chunks = [] + + # Подготовка задач для рабочих процессов + for worker_id in range(num_workers): + start_row = worker_id * rows_per_worker + end_row = (worker_id + 1) * rows_per_worker if worker_id < num_workers - 1 else size + chunks.append((matrix[start_row:end_row], worker_id)) + + with multiprocessing.Pool(processes=num_workers) as pool: + results = pool.starmap(compute_chunk_determinant, [(matrix, chunk[0], chunk[1]) for chunk in chunks]) + + return sum(results) + +# Вычисление детерминанта для части матрицы +def compute_chunk_determinant(matrix, chunk, chunk_id): + size = len(matrix) + result = 0 + for row in chunk: + for col in range(size): + submatrix = [r[:col] + r[col+1:] for r in matrix[1:]] + result += ((-1) ** (chunk_id + col)) * matrix[0][col] * compute_determinant(submatrix) + return result + +# Замер времени вычисления детерминанта +def measure_execution_time(dim, num_workers=1): + matrix = create_random_matrix(dim) + + start_time = time.time() + parallel_determinant_calculation(matrix, num_workers) + execution_time = time.time() - start_time + + return execution_time + +def main(): + # Размеры матриц + matrix_dimensions = [9, 10, 11] + # Список количества рабочих процессов + workers_list = [1, 2, 4, 6, 8] + + # Печать результатов бенчмарков + print("-*" * 40) + print(f"{'Количество рабочих процессов':<25}{'|9x9 (сек.)':<20}{'|10x10 (сек.)':<20}{'|11x11 (сек.)'}") + print("-*" * 40) + + for num_workers in workers_list: + row = f"{num_workers:<25}" + + for dim in matrix_dimensions: + execution_time = measure_execution_time(dim, num_workers) + row += f"|{execution_time:.4f}".ljust(20) + print(row) + print("-*" * 40) + +if __name__ == "__main__": + main()