mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-07-04 14:43:08 +02:00
add a new parallelization method
This commit is contained in:
parent
9ca9b35f8c
commit
f9a2a87e19
147
code/richardson_mpi.py
Normal file
147
code/richardson_mpi.py
Normal file
@ -0,0 +1,147 @@
|
||||
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)
|
||||
Loading…
Reference in New Issue
Block a user