mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-07-04 20:03:04 +02:00
git-subtree-dir: Programming/PORR git-subtree-mainline:9576b25315git-subtree-split:0a62d75a82
148 lines
4.6 KiB
Python
148 lines
4.6 KiB
Python
from mpi4py import MPI
|
|
import numpy as np
|
|
import time
|
|
|
|
def richardson_parallel(A, b, lambda_min, lambda_max, tol=1e-5, max_iter=10000):
|
|
comm = MPI.COMM_WORLD
|
|
rank = comm.Get_rank()
|
|
size = comm.Get_size()
|
|
|
|
# Rozmiar macierzy A
|
|
n = A.shape[0]
|
|
|
|
# Obliczanie wartości własnych tylko na jednym procesie
|
|
if rank == 0:
|
|
# eigenvalues = np.linalg.eigvals(A)
|
|
# lambda_min = np.min(eigenvalues)
|
|
# lambda_max = np.max(eigenvalues)
|
|
omega = 2 / (lambda_min + lambda_max)
|
|
else:
|
|
omega = None
|
|
|
|
# Rozgłoszenie omega do wszystkich procesów
|
|
omega = comm.bcast(omega, root=0)
|
|
|
|
# Inicjalizacja wektora rozwiązania jako float64
|
|
x = np.zeros_like(b, dtype=np.float64)
|
|
|
|
# Dzielimy pracę między procesy
|
|
local_rows = n // size
|
|
start_row = rank * local_rows
|
|
end_row = start_row + local_rows if rank != size - 1 else n
|
|
|
|
# Przydzielenie lokalnych porcji A i b
|
|
local_A = A[start_row:end_row, :]
|
|
local_b = b[start_row:end_row]
|
|
|
|
# Lokalny wektor residuum
|
|
local_r = np.zeros_like(local_b, dtype=np.float64)
|
|
|
|
# Globalny wektor residuum (pełny rozmiar b)
|
|
global_r = np.zeros_like(b, dtype=np.float64)
|
|
|
|
start_time = time.time()
|
|
|
|
for i in range(max_iter):
|
|
# Oblicz lokalny residuum r = b - A @ x
|
|
local_r[:] = local_b - np.dot(local_A, x)
|
|
|
|
# Tworzymy tymczasowy wektor o pełnym rozmiarze i kopiujemy lokalne dane
|
|
temp_r = np.zeros_like(b, dtype=np.float64)
|
|
temp_r[start_row:end_row] = local_r
|
|
|
|
# Sumujemy lokalne residuum przez wszystkie procesy
|
|
comm.Allreduce(temp_r, global_r, op=MPI.SUM)
|
|
|
|
# Aktualizujemy x równolegle na wszystkich procesach
|
|
x += omega * global_r
|
|
|
|
# Sprawdzamy warunek stopu (norma residuum)
|
|
if np.linalg.norm(global_r) < tol:
|
|
break
|
|
|
|
end_time = time.time()
|
|
|
|
execution_time = end_time - start_time
|
|
|
|
return x, execution_time
|
|
|
|
|
|
|
|
def check_solution(A, b, x_approx, tolerance=8e-3):
|
|
x_true = np.linalg.solve(A, b)
|
|
error = np.linalg.norm(x_true - x_approx)
|
|
return error < tolerance, error
|
|
|
|
if __name__ == "__main__":
|
|
comm = MPI.COMM_WORLD
|
|
rank = comm.Get_rank()
|
|
|
|
from matrix_generator import MatrixGenerator
|
|
sizes = [2, 5, 10, 50, 80, 100, 300, 500, 750, 1000, 5000, 10000]
|
|
for i in sizes:
|
|
if rank == 0:
|
|
A, b, lambda_min, lambda_max = MatrixGenerator.generate_matrix_and_vector('spd', size=i)
|
|
else:
|
|
A = None
|
|
b = None
|
|
lambda_min = None
|
|
lambda_max = None
|
|
|
|
A = comm.bcast(A, root=0)
|
|
b = comm.bcast(b, root=0)
|
|
|
|
# Rozwiązanie przy użyciu zrównoleglonej metody Richardsona
|
|
x, time_taken = richardson_parallel(A, b, lambda_min, lambda_max)
|
|
|
|
# Sprawdzanie poprawności rozwiązania (na procesie 0)
|
|
if rank == 0:
|
|
print(f"Spd matrix with size {i}")
|
|
is_correct, error = check_solution(A, b, x)
|
|
print("Czas wykonania [s]:", time_taken)
|
|
print("Czy rozwiązanie jest poprawne:", "Tak" if is_correct else "Nie")
|
|
print("Błąd rozwiązania:", error)
|
|
|
|
if rank == 0:
|
|
A, b, lambda_min, lambda_max = MatrixGenerator.generate_matrix_and_vector('nemeth12')
|
|
else:
|
|
A = None
|
|
b = None
|
|
lambda_min = None
|
|
lambda_max = None
|
|
|
|
A = comm.bcast(A, root=0)
|
|
b = comm.bcast(b, root=0)
|
|
|
|
# Rozwiązanie przy użyciu zrównoleglonej metody Richardsona
|
|
x, time_taken = richardson_parallel(A, b, lambda_min, lambda_max)
|
|
|
|
# Sprawdzanie poprawności rozwiązania (na procesie 0)
|
|
if rank == 0:
|
|
print(f"Nemeth12 matrix")
|
|
is_correct, error = check_solution(A, b, x)
|
|
print("Czas wykonania [s]:", time_taken)
|
|
print("Czy rozwiązanie jest poprawne:", "Tak" if is_correct else "Nie")
|
|
print("Błąd rozwiązania:", error)
|
|
|
|
if rank == 0:
|
|
A, b, lambda_min, lambda_max = MatrixGenerator.generate_matrix_and_vector('poli3')
|
|
else:
|
|
A = None
|
|
b = None
|
|
lambda_min = None
|
|
lambda_max = None
|
|
|
|
A = comm.bcast(A, root=0)
|
|
b = comm.bcast(b, root=0)
|
|
|
|
# Rozwiązanie przy użyciu zrównoleglonej metody Richardsona
|
|
x, time_taken = richardson_parallel(A, b, lambda_min, lambda_max)
|
|
|
|
# Sprawdzanie poprawności rozwiązania (na procesie 0)
|
|
if rank == 0:
|
|
print(f"Poli3 matrix")
|
|
is_correct, error = check_solution(A, b, x)
|
|
print("Czas wykonania [s]:", time_taken)
|
|
print("Czy rozwiązanie jest poprawne:", "Tak" if is_correct else "Nie")
|
|
print("Błąd rozwiązania:", error)
|