87 lines
4.2 KiB
Python
87 lines
4.2 KiB
Python
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] # Размеры матриц
|
||
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()
|