Add distributed computing for negation and addition (no memory distributing)
This commit is contained in:
parent
c0908b4299
commit
e6a9d5a2f0
@ -84,6 +84,25 @@ class Matrix:
|
||||
"""
|
||||
return self.__data__
|
||||
|
||||
@staticmethod
|
||||
def flatten(matrices: list):
|
||||
"""
|
||||
Flattens a list of matrices into one bigger matrix.
|
||||
The columns must match the first ``Matrix`` in the list and the rows can be arbitrarily.
|
||||
|
||||
:param matrices: A list of matrices.
|
||||
:type matrices: list
|
||||
:return: A ``Matrix`` extended by all matrices in the list.
|
||||
:rtype: ``Matrix``
|
||||
"""
|
||||
flattened_data = []
|
||||
rows = 0
|
||||
for matrix in matrices:
|
||||
flattened_data.extend(matrix.get_data())
|
||||
rows += matrix.__shape__[0]
|
||||
cols = matrices[0].__shape__[1]
|
||||
return Matrix(flattened_data, (rows, cols))
|
||||
|
||||
def shape(self):
|
||||
"""
|
||||
:return: the shape of the matrix, which is ``(rows, columns)``
|
||||
@ -219,7 +238,7 @@ class Matrix:
|
||||
def __rmul__(self, other):
|
||||
return self * other
|
||||
|
||||
def __abs_sum__(self):
|
||||
def __abs_sum_of_squares__(self):
|
||||
rows = self.__shape__[0]
|
||||
cols = self.__shape__[1]
|
||||
abs_sum = 0
|
||||
@ -258,7 +277,7 @@ class Matrix:
|
||||
:return: the norm as a number
|
||||
"""
|
||||
if f == "frobenius":
|
||||
norm = math.sqrt(self.__abs_sum__())
|
||||
norm = math.sqrt(self.__abs_sum_of_squares__())
|
||||
elif f == "col sum":
|
||||
norm = max(self.__col_sums__())
|
||||
elif f == "row sum":
|
||||
|
@ -5,9 +5,9 @@ from matrix import Matrix
|
||||
|
||||
|
||||
class MatrixMPI:
|
||||
__comm__ = MPI.COMM_WORLD
|
||||
__size__ = __comm__.Get_size()
|
||||
__rank__ = __comm__.Get_rank()
|
||||
__mpi_comm__ = MPI.COMM_WORLD
|
||||
__mpi_size__ = __mpi_comm__.Get_size()
|
||||
__mpi_rank__ = __mpi_comm__.Get_rank()
|
||||
|
||||
__matrix__: Matrix = None
|
||||
__chunk__: list = None
|
||||
@ -16,23 +16,103 @@ class MatrixMPI:
|
||||
self.__matrix__ = Matrix(data=data, shape=shape, structure=structure, model=model, offset=offset, n=n)
|
||||
|
||||
total_amount_of_rows = self.__matrix__.shape()[0]
|
||||
chunks = numpy.array_split(list(range(total_amount_of_rows)), self.__size__)
|
||||
self.__chunk__ = chunks[self.__rank__].tolist()
|
||||
chunks = numpy.array_split(list(range(total_amount_of_rows)), self.__mpi_size__)
|
||||
self.__chunk__ = chunks[self.__mpi_rank__].tolist()
|
||||
|
||||
@staticmethod
|
||||
def of(matrix: Matrix):
|
||||
return MatrixMPI(matrix.get_data(), matrix.shape())
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__matrix__)
|
||||
|
||||
def get_rank_data(self):
|
||||
def get_rank_submatrix(self):
|
||||
rows = len(self.__chunk__)
|
||||
cols = self.__matrix__.shape()[1]
|
||||
return Matrix(self.__matrix__[self.__chunk__], (rows, cols))
|
||||
|
||||
def transpose(self):
|
||||
return self.__matrix__.transpose()
|
||||
"""
|
||||
:return: the transpose of the matrix
|
||||
"""
|
||||
return MatrixMPI.of(self.__matrix__.transpose())
|
||||
|
||||
def T(self):
|
||||
"""
|
||||
Same as ``matrix.transpose()``
|
||||
|
||||
:return: see ``matrix.transpose()``
|
||||
"""
|
||||
return self.transpose()
|
||||
|
||||
def __eq__(self, other):
|
||||
"""
|
||||
Return ``self==value``
|
||||
|
||||
mpi_matrix = MatrixMPI(list(range(1, 25)), (12, 2))
|
||||
print(mpi_matrix.transpose())
|
||||
:param other: The object to compare to; must be either a ``MatrixMPI``, ``Matrix``, a ``list`` or a ``numpy.ndarray``
|
||||
:return: True if data in the matrix are equal to the given data in other for each component, otherwise False
|
||||
"""
|
||||
if isinstance(other, MatrixMPI):
|
||||
return self.__matrix__ == other.__matrix__
|
||||
else:
|
||||
return self.__matrix__ == other
|
||||
|
||||
def __neg__(self):
|
||||
gathered_data = self.__mpi_comm__.gather(-self.get_rank_submatrix())
|
||||
data = self.__mpi_comm__.bcast(gathered_data)
|
||||
return MatrixMPI.of(Matrix.flatten(data))
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, MatrixMPI):
|
||||
other = other.get_rank_submatrix()
|
||||
gathered_data = self.__mpi_comm__.gather(self.get_rank_submatrix() + other)
|
||||
data = self.__mpi_comm__.bcast(gathered_data)
|
||||
return MatrixMPI.of(Matrix.flatten(data))
|
||||
|
||||
def __radd__(self, other):
|
||||
return self + other
|
||||
|
||||
def __sub__(self, other):
|
||||
return self + (-other)
|
||||
|
||||
def __rsub__(self, other):
|
||||
return -self + other
|
||||
|
||||
def __truediv__(self, other):
|
||||
gathered_data = self.__mpi_comm__.gather(self.get_rank_submatrix() / other)
|
||||
data = self.__mpi_comm__.bcast(gathered_data)
|
||||
return MatrixMPI.of(Matrix.flatten(data))
|
||||
|
||||
def __mul__(self, other):
|
||||
if isinstance(other, MatrixMPI):
|
||||
return self.__matrix__ * other.__matrix__
|
||||
else:
|
||||
return self.__matrix__ * other
|
||||
|
||||
def __rmul__(self, other):
|
||||
return self * other
|
||||
|
||||
def norm(self, f: str = "frobenius"):
|
||||
"""
|
||||
Calculates the norm of the matrix.
|
||||
|
||||
A norm is a positive definit, absolute homogeneous and subadditive function.
|
||||
For Matrices a norm is also sub-multiplicative.
|
||||
|
||||
:param f: The norm to be used, could be either "frobenius", "row sum" or "col sum"
|
||||
|
||||
:return: the norm as a number
|
||||
"""
|
||||
return self.__matrix__.norm(f)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.__matrix__[key]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.__matrix__[key] = value
|
||||
|
||||
|
||||
# m1 = MatrixMPI(numpy.random.uniform(0, 1, 1_000_000), (1000, 1000))
|
||||
m1 = MatrixMPI([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6], (5, 3))
|
||||
|
||||
print(m1 - m1)
|
||||
|
@ -378,3 +378,12 @@ class TestMatrix(TestCase):
|
||||
expected = Matrix([1, 2, 3, 4, 5, 60, 70, 8, 9, 100, 110, 12, 13, 14, 15, 16], (4, 4))
|
||||
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_should_flatten_list_of_matrices(self):
|
||||
m1 = Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9], (3, 3))
|
||||
m2 = Matrix([1, 2, 3, 4, 5, 6], (2, 3))
|
||||
|
||||
actual = m1.flatten([m1, m2])
|
||||
expected = Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6], (5, 3))
|
||||
|
||||
self.assertEqual(expected, actual)
|
||||
|
Loading…
Reference in New Issue
Block a user