mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-07-04 14:43:08 +02:00
Time measurement feature (#6)
* making new branch and importing time * add time_measurement decorator * add measurement functionality to solve()
This commit is contained in:
parent
c938e63b7f
commit
73a12d3859
@ -2,6 +2,7 @@ import math
|
||||
from abc import ABC, abstractmethod
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from functools import partial
|
||||
from time_measurement import time_measurement, threads_time_accumulator
|
||||
|
||||
class LinearAlgebraUtils(ABC):
|
||||
@staticmethod
|
||||
@ -90,10 +91,9 @@ class SequentialLinearAlgebraUtils(ABC):
|
||||
return [x+y for x, y in zip(v1, v2)]
|
||||
|
||||
@staticmethod
|
||||
def scalar_vector_multiply(omega, vector): # na pewno scalar matrix? a nie scalar vector?
|
||||
def scalar_vector_multiply(omega, vector):
|
||||
return [omega * x for x in vector]
|
||||
|
||||
|
||||
@staticmethod
|
||||
def matrix_norm(A):
|
||||
return math.sqrt(sum(sum(element ** 2 for element in row) for row in A))
|
||||
@ -171,6 +171,7 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def dot_product(v1, v2):
|
||||
chunks = ThreadsLinearAlgebraUtils.divide_vectors_to_chunks(v1, v2)
|
||||
with ThreadPoolExecutor(max_workers=ThreadsLinearAlgebraUtils.NUM_THREADS) as executor:
|
||||
@ -178,6 +179,7 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
return sum(results)
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def matrix_vector_multiply(A, x):
|
||||
chunks = ThreadsLinearAlgebraUtils.divide_vector_or_matrix_to_chunks(A)
|
||||
with ThreadPoolExecutor(max_workers=ThreadsLinearAlgebraUtils.NUM_THREADS) as executor:
|
||||
@ -186,6 +188,7 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
return [item for sublist in results for item in sublist]
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def vector_norm(v):
|
||||
chunks = ThreadsLinearAlgebraUtils.divide_vector_or_matrix_to_chunks(v)
|
||||
|
||||
@ -198,6 +201,7 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
return total_sum**0.5
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def vector_scalar_divide(x, scalar):
|
||||
chunks = ThreadsLinearAlgebraUtils.divide_vector_or_matrix_to_chunks(x)
|
||||
|
||||
@ -206,6 +210,7 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
return [item for sublist in results for item in sublist]
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def matrix_scalar_multiply(A, w):
|
||||
chunks = ThreadsLinearAlgebraUtils.divide_vector_or_matrix_to_chunks(A)
|
||||
with ThreadPoolExecutor(max_workers=ThreadsLinearAlgebraUtils.NUM_THREADS) as executor:
|
||||
@ -213,6 +218,7 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
return [item for sublist in results for item in sublist]
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def vector_vector_subtraction(v1, v2):
|
||||
chunks = ThreadsLinearAlgebraUtils.divide_vectors_to_chunks(v1, v2)
|
||||
with ThreadPoolExecutor(max_workers=ThreadsLinearAlgebraUtils.NUM_THREADS) as executor:
|
||||
@ -221,6 +227,7 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def vector_vector_addition(v1, v2):
|
||||
chunks = ThreadsLinearAlgebraUtils.divide_vectors_to_chunks(v1, v2)
|
||||
with ThreadPoolExecutor(max_workers=ThreadsLinearAlgebraUtils.NUM_THREADS) as executor:
|
||||
@ -228,6 +235,7 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
return [item for sublist in results for item in sublist]
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def scalar_vector_multiply(omega, vector):
|
||||
chunks = ThreadsLinearAlgebraUtils.divide_vector_or_matrix_to_chunks(vector)
|
||||
with ThreadPoolExecutor(max_workers=ThreadsLinearAlgebraUtils.NUM_THREADS) as executor:
|
||||
@ -236,6 +244,7 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
return [item for sublist in results for item in sublist]
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def matrix_norm(A):
|
||||
chunks = ThreadsLinearAlgebraUtils.divide_vector_or_matrix_to_chunks(A)
|
||||
|
||||
@ -249,11 +258,13 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
return math.sqrt(total_sum)
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def divide_matrixes_to_chunks(A, B):
|
||||
chunk_size = len(A) // ThreadsLinearAlgebraUtils.NUM_THREADS
|
||||
return [(A[i:i + chunk_size], B[i:i + chunk_size]) for i in range(0, len(A), chunk_size)]
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def matrix_matrix_subtraction(A, B):
|
||||
|
||||
def subtract_chunk(pair):
|
||||
@ -266,6 +277,7 @@ class ThreadsLinearAlgebraUtils(ABC):
|
||||
return [row for chunk in results for row in chunk]
|
||||
|
||||
@staticmethod
|
||||
@time_measurement(threads_time_accumulator)
|
||||
def gaussian_elimination(A, b):
|
||||
n = len(A)
|
||||
M = [row[:] for row in A]
|
||||
|
||||
@ -4,6 +4,9 @@ from linear_algebra_utils import ThreadsLinearAlgebraUtils
|
||||
from eigenvalue_methods import EigenvalueMethods
|
||||
from matrix_generator import MatrixGenerator
|
||||
from processing_type import ProcessingType
|
||||
from time_measurement import threads_time_accumulator
|
||||
import time
|
||||
import gc
|
||||
|
||||
class RichardsonMethod:
|
||||
def __init__(self, method: ProcessingType, A, b, max_iterations, size: int, x0=None, tol=1e-5):
|
||||
@ -47,6 +50,9 @@ class RichardsonMethod:
|
||||
raise ValueError("Unknown method, please use 'SEQUENTIAL' or 'THREADS'.")
|
||||
|
||||
def solve(self):
|
||||
gc.disable()
|
||||
threads_time_accumulator.total_time = 0
|
||||
start = time.time()
|
||||
x = self.x0[:]
|
||||
#if RichardsonMethod.convergence_norm(self.LinAlg, self.A, self.omega, self.I) >= 1:
|
||||
# return RichardsonMethod.convergence_norm(self.A, self.omega, self.I), "Richardson method for those values will NOT converge",
|
||||
@ -56,4 +62,13 @@ class RichardsonMethod:
|
||||
residual = self.LinAlg.vector_vector_subtraction(self.b, Ax)
|
||||
x = self.LinAlg.vector_vector_addition(x, self.LinAlg.scalar_vector_multiply(self.omega, residual))
|
||||
|
||||
end = time.time()
|
||||
total_time = end - start
|
||||
gc.enable()
|
||||
if(self.LinAlg == SequentialLinearAlgebraUtils):
|
||||
print(f"Total: {total_time:.3e}s")
|
||||
elif(self.LinAlg == ThreadsLinearAlgebraUtils):
|
||||
sequential_time = total_time - threads_time_accumulator.total_time
|
||||
print(f"Total: {total_time:.3e}s, Seq: {sequential_time:.3e}s, Parallel: {threads_time_accumulator.total_time:.3e}s")
|
||||
|
||||
return x, 0
|
||||
|
||||
@ -32,13 +32,21 @@ def calcualte_norm_from_matrix_numpy(A, n, max_iterations):
|
||||
|
||||
@pytest.mark.parametrize("n", [2, 3, 4, 5, 10, 20, 50, 100])
|
||||
@pytest.mark.parametrize("processing_type", [ProcessingType.SEQUENTIAL, ProcessingType.THREADS])
|
||||
def test_richardson_vs_cg(n: int, processing_type: ProcessingType):
|
||||
def test_richardson_vs_cg(n: int, processing_type: ProcessingType, capsys):
|
||||
print("matrix size: ", n)
|
||||
tolerance = 1e-5
|
||||
max_iterations=1000
|
||||
A, b = MatrixGenerator.generate_random_matrix_and_vector(n)
|
||||
richardson_solver = RichardsonMethod(processing_type, A, b, max_iterations, size=n, tol=1e-7)
|
||||
solution_richardson, info_richardson = richardson_solver.solve()
|
||||
# solution_richardson, info_richardson = richardson_solver.solve()
|
||||
|
||||
solution_richardson, info_richardson = None, None
|
||||
with capsys.disabled():
|
||||
solution_richardson, info_richardson = richardson_solver.solve()
|
||||
|
||||
# Przechwytywanie wyjścia po solve
|
||||
captured = capsys.readouterr()
|
||||
print("Captured output:", captured.out)
|
||||
|
||||
solution_cg, info = cg(A, b)
|
||||
|
||||
|
||||
24
code/time_measurement.py
Normal file
24
code/time_measurement.py
Normal file
@ -0,0 +1,24 @@
|
||||
import time
|
||||
from functools import wraps
|
||||
|
||||
class TimeAccumulator:
|
||||
def __init__(self):
|
||||
self.total_time = 0
|
||||
|
||||
threads_time_accumulator = TimeAccumulator()
|
||||
|
||||
def time_measurement(accumulator):
|
||||
def decorator(func):
|
||||
@wraps(func)
|
||||
def inner(*args, **kwargs):
|
||||
start = time.time()
|
||||
result = func(*args, **kwargs)
|
||||
end = time.time()
|
||||
accumulator.total_time += end - start
|
||||
return result
|
||||
return inner
|
||||
return decorator
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user