Skip to content

Commit b716f07

Browse files
committed
Use mul! in SYMMLQ
1 parent 632a37e commit b716f07

File tree

4 files changed

+35
-27
lines changed

4 files changed

+35
-27
lines changed

src/krylov_solvers.jl

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,22 @@ The outer constructors
133133
may be used in order to create these vectors.
134134
"""
135135
mutable struct SymmlqSolver{T,S} <: KrylovSolver{T,S}
136-
x :: S
137-
Mvold :: S
138-
Mv :: S
139-
:: S
136+
x :: S
137+
Mvold :: S
138+
Mv :: S
139+
Mv_next :: S
140+
:: S
141+
v :: Union{S, Nothing}
140142

141143
function SymmlqSolver(n, m, S)
142-
T = eltype(S)
143-
x = S(undef, n)
144-
Mvold = S(undef, n)
145-
Mv = S(undef, n)
146-
= S(undef, n)
147-
solver = new{T,S}(x, Mvold, Mv, w̅)
144+
T = eltype(S)
145+
x = S(undef, n)
146+
Mvold = S(undef, n)
147+
Mv = S(undef, n)
148+
Mv_next = S(undef, n)
149+
= S(undef, n)
150+
v = nothing
151+
solver = new{T,S}(x, Mvold, Mv, Mv_next, w̅, v)
148152
return solver
149153
end
150154

src/symmlq.jl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,22 @@ function symmlq!(solver :: SymmlqSolver{T,S}, A, b :: AbstractVector{T};
4848

4949
m, n = size(A)
5050
m == n || error("System must be square")
51-
size(b, 1) == m || error("Inconsistent problem size")
51+
length(b) == m || error("Inconsistent problem size")
5252
(verbose > 0) && @printf("SYMMLQ: system of size %d\n", n)
5353

54-
# Test M == Iₘ
55-
MisI = isa(M, opEye)
54+
# Tests M == Iₙ
55+
MisI = isa(M, opEye) || (M == I)
5656

5757
# Check type consistency
5858
eltype(A) == T || error("eltype(A) ≠ $T")
5959
ktypeof(b) == S || error("ktypeof(b) ≠ $S")
6060
MisI || (eltype(M) == T) || error("eltype(M) ≠ $T")
6161

6262
# Set up workspace.
63-
x, Mvold, Mv, w̅ = solver.x, solver.Mvold, solver.Mv, solver.
63+
!MisI && isnothing(solver.v) && (solver.v = S(undef, n))
64+
x, Mvold, Mv, Mv_next, w̅ = solver.x, solver.Mvold, solver.Mv, solver.Mv_next, solver.
65+
v = MisI ? Mv : solver.v
66+
vold = MisI ? Mvold : solver.v
6467

6568
ϵM = eps(T)
6669
x .= zero(T)
@@ -69,7 +72,7 @@ function symmlq!(solver :: SymmlqSolver{T,S}, A, b :: AbstractVector{T};
6972
# Initialize Lanczos process.
7073
# β₁ M v₁ = b.
7174
Mvold .= b
72-
vold = M * Mvold
75+
MisI || mul!(vold, M, Mvold)
7376
β₁ = @kdot(m, vold, Mvold)
7477
β₁ == 0 && return (x, SimpleStats(true, true, [zero(T)], [zero(T)], "x = 0 is a zero-residual solution"))
7578
β₁ = sqrt(β₁)
@@ -79,10 +82,10 @@ function symmlq!(solver :: SymmlqSolver{T,S}, A, b :: AbstractVector{T};
7982

8083
w̅ .= vold
8184

82-
Mv .= A * vold
85+
mul!(Mv, A, vold)
8386
α = @kdot(m, vold, Mv) + λ
8487
@kaxpy!(m, -α, Mvold, Mv) # Mv = Mv - α * Mvold
85-
v = M * Mv
88+
MisI || mul!(v, M, Mv)
8689
β = @kdot(m, v, Mv)
8790
β < 0 && error("Preconditioner is not positive definite")
8891
β = sqrt(β)
@@ -177,13 +180,13 @@ function symmlq!(solver :: SymmlqSolver{T,S}, A, b :: AbstractVector{T};
177180

178181
# Generate next Lanczos vector
179182
oldβ = β
180-
Mv_next = A * v
183+
mul!(Mv_next, A, v)
181184
α = @kdot(m, v, Mv_next) + λ
182185
@kaxpy!(m, -oldβ, Mvold, Mv_next)
183186
@. Mvold = Mv
184187
@kaxpy!(m, -α, Mv, Mv_next)
185188
@. Mv = Mv_next
186-
v = M * Mv
189+
MisI || mul!(v, M, Mv)
187190
β = @kdot(m, v, Mv)
188191
β < 0 && error("Preconditioner is not positive definite")
189192
β = sqrt(β)

src/variants.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ for fn in (:cgls, :cgne, :lnlq, :craig, :craigmr, :crls, :crmr, :lslq, :lsqr, :l
3434
end
3535

3636
# Variants where matrix-vector products with A are only required
37-
for fn in (:symmlq, :cgs, :bicgstab)
37+
for fn in (:cgs, :bicgstab)
3838
@eval begin
3939
$fn(A :: AbstractMatrix{T}, b :: AbstractVector{T}; kwargs...) where T <: AbstractFloat =
4040
$fn(PreallocatedLinearOperator(A, storagetype=ktypeof(b), symmetric=true), b; wrap_preconditioners(kwargs, ktypeof(b))...)

test/test_alloc.jl

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,19 @@ function test_alloc()
2323
UniformScaling_bytes = @allocated cg(L, b, M=M2)
2424
@test 0.99 * UniformScaling_bytes opEye_bytes 1.01 * UniformScaling_bytes
2525

26-
# without preconditioner and with Ap preallocated, SYMMLQ needs 4 n-vectors: x_lq, vold, v, w̅ (= x_cg)
27-
storage_symmlq(n) = 4 * n
26+
# SYMMLQ needs:
27+
# 5 n-vectors: x, Mvold, Mv, Mv_next, w̅
28+
storage_symmlq(n) = 5 * n
2829
storage_symmlq_bytes(n) = 8 * storage_symmlq(n)
2930

3031
expected_symmlq_bytes = storage_symmlq_bytes(n)
31-
symmlq(A, b) # warmup
32-
actual_symmlq_bytes = @allocated symmlq(A, b)
32+
symmlq(L, b) # warmup
33+
actual_symmlq_bytes = @allocated symmlq(L, b)
3334
@test actual_symmlq_bytes 1.1 * expected_symmlq_bytes
3435

35-
solver = SymmlqSolver(A, b)
36-
symmlq!(solver, A, b) # warmup
37-
inplace_symmlq_bytes = @allocated symmlq!(solver, A, b)
36+
solver = SymmlqSolver(L, b)
37+
symmlq!(solver, L, b) # warmup
38+
inplace_symmlq_bytes = @allocated symmlq!(solver, L, b)
3839
@test (VERSION < v"1.5") || (inplace_symmlq_bytes == 672)
3940

4041
# CG needs:

0 commit comments

Comments
 (0)