2024-11-13 19:59:58 +04:00
|
|
|
|
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():
|
2024-12-30 21:35:39 +04:00
|
|
|
|
sizes = [100, 300, 500] # Размеры матриц
|
2024-11-13 19:59:58 +04:00
|
|
|
|
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()
|