Skip to content

Commit 053e52d

Browse files
committed
minor: fix flake8
1 parent ae5661b commit 053e52d

File tree

3 files changed

+55
-54
lines changed

3 files changed

+55
-54
lines changed

examples/plot_matrixmult.py

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
"""
1+
r"""
22
Distributed Matrix Multiplication
33
=================================
44
This example shows how to use the :py:class:`pylops_mpi.basicoperators.MPIMatrixMult`
5-
operator to perform matrix-matrix multiplication between a matrix :math:`\mathbf{A}`
5+
operator to perform matrix-matrix multiplication between a matrix :math:`\mathbf{A}`
66
blocked over rows (i.e., blocks of rows are stored over different ranks) and a
7-
matrix :math:`\mathbf{X}` blocked over columns (i.e., blocks of columns are
8-
stored over different ranks), with equal number of row and column blocks.
9-
Similarly, the adjoint operation can be peformed with a matrix :math:`\mathbf{Y}`
7+
matrix :math:`\mathbf{X}` blocked over columns (i.e., blocks of columns are
8+
stored over different ranks), with equal number of row and column blocks.
9+
Similarly, the adjoint operation can be peformed with a matrix :math:`\mathbf{Y}`
1010
blocked in the same fashion of matrix :math:`\mathbf{X}`.
1111
12-
Note that whilst the different blocks of the matrix :math:`\mathbf{A}` are directly
13-
stored in the operator on different ranks, the matrix :math:`\mathbf{X}` is
14-
effectively represented by a 1-D :py:class:`pylops_mpi.DistributedArray` where
12+
Note that whilst the different blocks of the matrix :math:`\mathbf{A}` are directly
13+
stored in the operator on different ranks, the matrix :math:`\mathbf{X}` is
14+
effectively represented by a 1-D :py:class:`pylops_mpi.DistributedArray` where
1515
the different blocks are flattened and stored on different ranks. Note that to
16-
optimize communications, the ranks are organized in a 2D grid and some of the
17-
row blocks of :math:`\mathbf{A}` and column blocks of :math:`\mathbf{X}` are
18-
replicated across different ranks - see below for details.
16+
optimize communications, the ranks are organized in a 2D grid and some of the
17+
row blocks of :math:`\mathbf{A}` and column blocks of :math:`\mathbf{X}` are
18+
replicated across different ranks - see below for details.
1919
2020
"""
2121

@@ -30,17 +30,17 @@
3030
plt.close("all")
3131

3232
###############################################################################
33-
# We set the seed such that all processes can create the input matrices filled
34-
# with the same random number. In practical application, such matrices will be
33+
# We set the seed such that all processes can create the input matrices filled
34+
# with the same random number. In practical application, such matrices will be
3535
# filled with data that is appropriate that is appropriate the use-case.
3636
np.random.seed(42)
3737

3838
###############################################################################
39-
# Next we obtain the MPI parameters for each rank and check that the number
39+
# Next we obtain the MPI parameters for each rank and check that the number
4040
# of processes (``size``) is a square number
4141
comm = MPI.COMM_WORLD
42-
rank = comm.Get_rank() # rank of current process
43-
size = comm.Get_size() # number of processes
42+
rank = comm.Get_rank() # rank of current process
43+
size = comm.Get_size() # number of processes
4444

4545
p_prime = math.isqrt(size)
4646
repl_factor = p_prime
@@ -58,7 +58,7 @@
5858
X = np.random.rand(K * M).astype(dtype=np.float32).reshape(K, M)
5959

6060
################################################################################
61-
# The processes are now arranged in a :math:`\sqrt{P} \times \sqrt{P}` grid,
61+
# The processes are now arranged in a :math:`\sqrt{P} \times \sqrt{P}` grid,
6262
# where :math:`P` is the total number of processes.
6363
#
6464
# We define
@@ -71,7 +71,7 @@
7171
# .. math::
7272
# R = \bigl\lceil \tfrac{P}{P'} \bigr\rceil.
7373
#
74-
# Each process is therefore assigned a pair of coordinates
74+
# Each process is therefore assigned a pair of coordinates
7575
# :math:`(r,c)` within this grid:
7676
#
7777
# .. math::
@@ -101,7 +101,7 @@
101101
col_comm = comm.Split(color=my_col, key=my_row) # all procs in same col
102102

103103
################################################################################
104-
# At this point we divide the rows and columns of :math:`\mathbf{A}` and
104+
# At this point we divide the rows and columns of :math:`\mathbf{A}` and
105105
# :math:`\mathbf{X}`, respectively, such that each rank ends up with:
106106
#
107107
# - :math:`A_{p} \in \mathbb{R}^{\text{my_own_rows}\times K}`
@@ -147,12 +147,12 @@
147147
A_p, X_p = A[rs:re, :].copy(), X[:, cs:ce].copy()
148148

149149
################################################################################
150-
# We are now ready to create the :py:class:`pylops_mpi.basicoperators.MPIMatrixMult`
150+
# We are now ready to create the :py:class:`pylops_mpi.basicoperators.MPIMatrixMult`
151151
# operator and the input matrix :math:`\mathbf{X}`
152152
Aop = MPIMatrixMult(A_p, M, dtype="float32")
153153

154154
col_lens = comm.allgather(my_own_cols)
155-
total_cols = np.sum(col_lens)
155+
total_cols = np.sum(col_lens)
156156
x = DistributedArray(global_shape=K * total_cols,
157157
local_shapes=[K * col_len for col_len in col_lens],
158158
partition=Partition.SCATTER,
@@ -162,22 +162,22 @@
162162
x[:] = X_p.flatten()
163163

164164
################################################################################
165-
# We can now apply the forward pass :math:`\mathbf{y} = \mathbf{Ax}` (which effectively
165+
# We can now apply the forward pass :math:`\mathbf{y} = \mathbf{Ax}` (which effectively
166166
# implements a distributed matrix-matrix multiplication :math:`Y = \mathbf{AX}`)
167-
# Note :math:`\mathbf{Y}` is distributed in the same way as the input
167+
# Note :math:`\mathbf{Y}` is distributed in the same way as the input
168168
# :math:`\mathbf{X}`.
169169
y = Aop @ x
170170

171171
###############################################################################
172-
# Next we apply the adjoint pass :math:`\mathbf{x}_{adj} = \mathbf{A}^H \mathbf{x}`
173-
# (which effectively implements a distributed matrix-matrix multiplication
172+
# Next we apply the adjoint pass :math:`\mathbf{x}_{adj} = \mathbf{A}^H \mathbf{x}`
173+
# (which effectively implements a distributed matrix-matrix multiplication
174174
# :math:`\mathbf{X}_{adj} = \mathbf{A}^H \mathbf{X}`). Note that
175-
# :math:`\mathbf{X}_{adj}` is again distributed in the same way as the input
175+
# :math:`\mathbf{X}_{adj}` is again distributed in the same way as the input
176176
# :math:`\mathbf{X}`.
177177
xadj = Aop.H @ y
178178

179179
###############################################################################
180-
# To conclude we verify our result against the equivalent serial version of
180+
# To conclude we verify our result against the equivalent serial version of
181181
# the operation by gathering the resulting matrices in rank0 and reorganizing
182182
# the returned 1D-arrays into 2D-arrays.
183183

@@ -210,15 +210,15 @@
210210
xadj_loc = (A.T.dot(y_loc.conj())).conj().squeeze()
211211

212212
if not np.allclose(y, y_loc, rtol=1e-6):
213-
print(f" FORWARD VERIFICATION FAILED")
214-
print(f'distributed: {y}')
213+
print("FORWARD VERIFICATION FAILED")
214+
print(f'distributed: {y}')
215215
print(f'expected: {y_loc}')
216216
else:
217-
print(f"FORWARD VERIFICATION PASSED")
217+
print("FORWARD VERIFICATION PASSED")
218218

219219
if not np.allclose(xadj, xadj_loc, rtol=1e-6):
220-
print(f" ADJOINT VERIFICATION FAILED")
221-
print(f'distributed: {xadj}')
220+
print("ADJOINT VERIFICATION FAILED")
221+
print(f'distributed: {xadj}')
222222
print(f'expected: {xadj_loc}')
223223
else:
224-
print(f"ADJOINT VERIFICATION PASSED")
224+
print("ADJOINT VERIFICATION PASSED")

pylops_mpi/basicoperators/MatrixMult.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
class MPIMatrixMult(MPILinearOperator):
1515
r"""MPI Matrix multiplication
16-
17-
Implement distributed matrix-matrix multiplication between a matrix
16+
17+
Implement distributed matrix-matrix multiplication between a matrix
1818
:math:`\mathbf{A}` blocked over rows (i.e., blocks of rows are stored
1919
over different ranks) and the input model and data vector, which are both to
2020
be interpreted as matrices blocked over columns.
@@ -26,7 +26,7 @@ class MPIMatrixMult(MPILinearOperator):
2626
where :math:`N_{loc}` is the number of rows stored on this MPI rank and
2727
``K`` is the global number of columns.
2828
M : :obj:`int`
29-
Global leading dimension (i.e., number of columns) of the matrices
29+
Global leading dimension (i.e., number of columns) of the matrices
3030
representing the input model and data vectors.
3131
saveAt : :obj:`bool`, optional
3232
Save ``A`` and ``A.H`` to speed up the computation of adjoint
@@ -52,24 +52,24 @@ class MPIMatrixMult(MPILinearOperator):
5252
5353
Notes
5454
-----
55-
This operator performs a matrix-matrix multiplication, whose forward
55+
This operator performs a matrix-matrix multiplication, whose forward
5656
operation can be described as :math:`Y = A \cdot X` where:
5757
5858
- :math:`\mathbf{A}` is the distributed matrix operator of shape :math:`[N \times K]`
5959
- :math:`\mathbf{X}` is the distributed operand matrix of shape :math:`[K \times M]`
6060
- :math:`\mathbf{Y}` is the resulting distributed matrix of shape :math:`[N \times M]`
6161
62-
whilst the adjoint operation is represented by
63-
:math:`\mathbf{X}_{adj} = \mathbf{A}^H \cdot \mathbf{Y}` where
62+
whilst the adjoint operation is represented by
63+
:math:`\mathbf{X}_{adj} = \mathbf{A}^H \cdot \mathbf{Y}` where
6464
:math:`\mathbf{A}^H` is the complex conjugate and transpose of :math:`\mathbf{A}`.
65-
66-
This implementation is based on a 1D block distribution of the operator
65+
66+
This implementation is based on a 1D block distribution of the operator
6767
matrix and reshaped model and data vectors replicated across :math:`P`
68-
processes by a factor equivalent to :math:`\sqrt{P}` across a square process
68+
processes by a factor equivalent to :math:`\sqrt{P}` across a square process
6969
grid (:math:`\sqrt{P}\times\sqrt{P}`). More specifically:
7070
7171
- The matrix ``A`` is distributed across MPI processes in a block-row fashion
72-
and each process holds a local block of ``A`` with shape
72+
and each process holds a local block of ``A`` with shape
7373
:math:`[N_{loc} \times K]`
7474
- The operand matrix ``X`` is distributed in a block-column fashion and
7575
each process holds a local block of ``X`` with shape
@@ -111,7 +111,7 @@ class MPIMatrixMult(MPILinearOperator):
111111
sum of the contributions from all column blocks of ``A^H``, processes in
112112
the same row perform an ``allreduce`` sum to combine their partial results.
113113
This gives the complete ``(K, M_local)`` result for their assigned column.
114-
114+
115115
"""
116116
def __init__(
117117
self,
@@ -125,7 +125,7 @@ def __init__(
125125
size = base_comm.Get_size()
126126

127127
# Determine grid dimensions (P_prime × C) such that P_prime * C ≥ size
128-
self._P_prime = math.isqrt(size)
128+
self._P_prime = math.isqrt(size)
129129
self._C = self._P_prime
130130
if self._P_prime * self._C != size:
131131
raise Exception(f"Number of processes must be a square number, provided {size} instead...")
@@ -138,7 +138,8 @@ def __init__(
138138
self._col_comm = base_comm.Split(color=self._col_id, key=self._row_id)
139139

140140
self.A = A.astype(np.dtype(dtype))
141-
if saveAt: self.At = A.T.conj()
141+
if saveAt:
142+
self.At = A.T.conj()
142143

143144
self.N = self._row_comm.allreduce(self.A.shape[0], op=MPI.SUM)
144145
self.K = A.shape[1]

tests/test_matrixmult.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
pytest.param(37, 37, 37, "float32", id="f32_37_37_37"),
2424
pytest.param(50, 30, 40, "float64", id="f64_50_30_40"),
2525
pytest.param(22, 20, 16, "complex64", id="c64_22_20_16"),
26-
pytest.param( 3, 4, 5, "float32", id="f32_3_4_5"),
27-
pytest.param( 1, 2, 1, "float64", id="f64_1_2_1",),
28-
pytest.param( 2, 1, 3, "float32", id="f32_2_1_3",),
26+
pytest.param(3, 4, 5, "float32", id="f32_3_4_5"),
27+
pytest.param(1, 2, 1, "float64", id="f64_1_2_1",),
28+
pytest.param(2, 1, 3, "float32", id="f32_2_1_3",),
2929
]
3030

3131

@@ -34,8 +34,8 @@
3434
def test_SUMMAMatrixMult(N, K, M, dtype_str):
3535
p_prime = math.isqrt(size)
3636
C = p_prime
37-
if p_prime * C != size:
38-
pytest.skip(f"Number of processes must be a square number, "
37+
if p_prime * C != size:
38+
pytest.skip("Number of processes must be a square number, "
3939
"provided {size} instead...")
4040

4141
dtype = np.dtype(dtype_str)
@@ -68,8 +68,8 @@ def test_SUMMAMatrixMult(N, K, M, dtype_str):
6868
X_glob_imag = np.arange(K * M, dtype=base_float_dtype).reshape(K, M) * 0.7
6969
X_glob = (X_glob_real + cmplx * X_glob_imag).astype(dtype)
7070

71-
A_p = A_glob[row_start_A:row_end_A,:]
72-
X_p = X_glob[:,col_start_X:col_end_X]
71+
A_p = A_glob[row_start_A:row_end_A, :]
72+
X_p = X_glob[:, col_start_X:col_end_X]
7373

7474
# Create MPIMatrixMult operator
7575
Aop = MPIMatrixMult(A_p, M, base_comm=comm, dtype=dtype_str)
@@ -137,4 +137,4 @@ def test_SUMMAMatrixMult(N, K, M, dtype_str):
137137
)
138138

139139
col_comm.Free()
140-
row_comm.Free()
140+
row_comm.Free()

0 commit comments

Comments
 (0)