diff --git a/agliullov_daniyar_lab_6/Screenshots/Снимок экрана 2024-11-13 195622.png b/agliullov_daniyar_lab_6/Screenshots/Снимок экрана 2024-11-13 195622.png new file mode 100644 index 0000000..48a15c6 Binary files /dev/null and b/agliullov_daniyar_lab_6/Screenshots/Снимок экрана 2024-11-13 195622.png differ diff --git a/agliullov_daniyar_lab_6/main.py b/agliullov_daniyar_lab_6/main.py new file mode 100644 index 0000000..ab7c9b9 --- /dev/null +++ b/agliullov_daniyar_lab_6/main.py @@ -0,0 +1,86 @@ +import numpy as np +import time +from multiprocessing import Pool + +np.seterr(over='ignore') + +# Функция для вычисления детерминанта методом Гаусса +def compute_determinant_gauss(mat): + size = mat.shape[0] + matrix_copy = mat.astype(float) # Копируем матрицу, чтобы не изменять исходную + determinant = 1.0 # Начальное значение детерминанта + + for k in range(size): + # Находим максимальный элемент в текущем столбце для уменьшения ошибок округления + max_index = np.argmax(np.abs(matrix_copy[k:size, k])) + k + if matrix_copy[max_index, k] == 0: + return 0 # Если на главной диагонали ноль, детерминант равен нулю + # Меняем местами строки + if max_index != k: + matrix_copy[[k, max_index]] = matrix_copy[[max_index, k]] + determinant *= -1 # Каждая перестановка меняет знак детерминанта + # Обнуляем элементы ниже главной диагонали + for m in range(k + 1, size): + multiplier = matrix_copy[m, k] / matrix_copy[k, k] + matrix_copy[m, k:] -= multiplier * matrix_copy[k, k:] + + # Произведение элементов на главной диагонали + for j in range(size): + determinant *= matrix_copy[j, j] + return determinant + +# Функция для параллельного вычисления детерминанта +def parallel_worker(index_range, mat): + size = mat.shape[0] + matrix_copy = mat.astype(float) + det = 1.0 + + for k in range(index_range[0], index_range[1]): + max_index = np.argmax(np.abs(matrix_copy[k:size, k])) + k + if matrix_copy[max_index, k] == 0: + return 0 + if max_index != k: + matrix_copy[[k, max_index]] = matrix_copy[[max_index, k]] + det *= -1 + for m in range(k + 1, size): + multiplier = matrix_copy[m, k] / matrix_copy[k, k] + matrix_copy[m, k:] -= multiplier * matrix_copy[k, k:] + return det + +# Функция для параллельного вычисления детерминанта +def compute_parallel_determinant(mat, num_workers): + size = mat.shape[0] + block_size = size // num_workers + ranges = [(i * block_size, (i + 1) * block_size) for i in range(num_workers)] + + with Pool(processes=num_workers) as pool: + results = pool.starmap(parallel_worker, [(block, mat) for block in ranges]) + + # Объединяем результаты + total_determinant = sum(results) + return total_determinant + +# Функция для запуска тестов производительности +def execute_benchmarks(): + sizes = [100, 300, 500, 1000, 1200] # Размеры матриц + for size in sizes: + random_matrix = np.random.rand(size, size) # Генерация случайной матрицы + print(f"--- Тест производительности для матрицы {size}x{size} ---") + + # Последовательное вычисление детерминанта + start_time = time.time() + sequential_det = compute_determinant_gauss(random_matrix) + seq_duration = time.time() - start_time + print(f"Время последовательного вычисления для {size}x{size}: {seq_duration:.4f} секунд") + + # Параллельное вычисление с различным количеством процессов + for workers in [1, 2, 4, 6, 8, 12, 16]: + start_time = time.time() + parallel_det = compute_parallel_determinant(random_matrix, workers) + par_duration = time.time() - start_time + speedup_ratio = seq_duration / par_duration if par_duration > 0 else 0 + print(f"Параллельное время с {workers} процессами: {par_duration:.4f} секунд, Ускорение: {speedup_ratio:.2f}") + +# Запуск тестов производительности +if __name__ == '__main__': + execute_benchmarks() diff --git a/agliullov_daniyar_lab_6/readme.md b/agliullov_daniyar_lab_6/readme.md new file mode 100644 index 0000000..dc8c45c --- /dev/null +++ b/agliullov_daniyar_lab_6/readme.md @@ -0,0 +1,15 @@ +# Аглиуллов Данияр ИСЭбд-41 +# Лабораторная работа №6 + + Для повышения производительности при вычислении детерминанта для больших матриц была добавлена возможность параллельной обработки с использованием библиотеки multiprocessing. Это позволило значительно ускорить вычисления за счет распределения нагрузки между несколькими процессами. + +Результаты тестов: +![изображение 1](../Screenshots/1.png) + +Сравнение производительности: + + • В тестах на матрицах размером 100x100, 300x300 и 500x500 было замечено, что параллельный алгоритм демонстрирует значительное сокращение времени выполнения по сравнению с обычным алгоритмом, особенно на больших матрицах. Это подтверждает эффективность использования многопоточности для задач, требующих больших вычислительных ресурсов. + + • На малых размерах матриц (например, 100x100) преимущество было за последовательным умножением матрицы из-за накладных расходов на создание пула потоков. Однако при увеличении размера матрицы (300x300 и 500x500) преимущества параллельного подхода становились более очевидными. + • При превышении количества физических потоков процессора, производительность понижается за счет смены контекста при переключении виртуальных потоков на одном ядре + \ No newline at end of file