Skip to content

Commit dbd1cd1

Browse files
committed
reduce allocation all PredictiveControllers
1 parent a27080e commit dbd1cd1

File tree

2 files changed

+59
-35
lines changed

2 files changed

+59
-35
lines changed

src/controller/execute.jl

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ end
143143
Init linear model prediction matrices `F, q̃, p` and current estimated output `ŷ`.
144144
145145
See [`init_predmat`](@ref) and [`init_quadprog`](@ref) for the definition of the matrices.
146-
They are computed with:
146+
They are computed with these equations using in-place operations:
147147
```math
148148
\begin{aligned}
149149
\mathbf{F} &= \mathbf{G d}(k) + \mathbf{J D̂} + \mathbf{K x̂}_{k-1}(k) + \mathbf{V u}(k-1) \\
@@ -155,24 +155,32 @@ They are computed with:
155155
```
156156
"""
157157
function initpred!(mpc::PredictiveController, model::LinModel, d, ym, D̂, R̂y, R̂u)
158-
mpc.ŷ[:] = evalŷ(mpc.estim, ym, d)
158+
ŷ, F, q̃, p = mpc.ŷ, mpc.F, mpc.q̃, mpc.p
159+
ŷ .= evalŷ(mpc.estim, ym, d)
159160
predictstoch!(mpc, mpc.estim, d, ym) # init mpc.Ŷop for InternalModel
160-
mpc.F[:] = mpc.K * mpc.estim.+ mpc.V * mpc.estim.lastu0 + mpc.Ŷop
161+
F_LHS = similar(F)
162+
F .= mul!(F_LHS, mpc.K, mpc.estim.x̂)
163+
F .+= mul!(F_LHS, mpc.V, mpc.estim.lastu0)
164+
F .+= mpc.Ŷop
161165
if model.nd 0
162-
mpc.d0[:], mpc.D̂0[:] = d - model.dop, D̂ - mpc.Dop
163-
mpc.D̂E[:] = [d; D̂]
164-
mpc.F[:] = mpc.F + mpc.G * mpc.d0 + mpc.J * mpc.D̂0
166+
mpc.d0 .= d .- model.dop
167+
mpc.D̂0 .=.- mpc.Dop
168+
mpc.D̂E[1:model.nd] .= mpc.d0
169+
mpc.D̂E[model.nd+1:end] .= mpc.D̂0
170+
F .+= mul!(F_LHS, mpc.G, mpc.d0)
171+
F .+= mul!(F_LHS, mpc.J, mpc.D̂0)
165172
end
166-
mpc.R̂y[:] = R̂y
167-
C_y = mpc.F - mpc.R̂y
168-
mpc.q̃[:] = 2(mpc.M_Hp*mpc.Ẽ)'*C_y
169-
mpc.p[] = dot(C_y, mpc.M_Hp, C_y)
173+
mpc.R̂y .= R̂y
174+
C_y = F_LHS
175+
C_y .= mpc.F .- mpc.R̂y
176+
q̃ .= lmul!(2,(mpc.M_Hp*mpc.Ẽ)'*C_y)
177+
p .= dot(C_y, mpc.M_Hp, C_y)
170178
if ~mpc.noR̂u
171-
mpc.R̂u[:] = R̂u
179+
mpc.R̂u .= R̂u
172180
lastu = mpc.estim.lastu0 + model.uop
173181
C_u = mpc.T*lastu - mpc.R̂u
174-
mpc.[:] = mpc.+ 2(mpc.L_Hp*mpc.S̃)'*C_u
175-
mpc.p[] = mpc.p[] + dot(C_y, mpc.L_Hp, C_u)
182+
mpc. .+= lmul!(2, (mpc.L_Hp*mpc.S̃)'*C_u)
183+
mpc.p .+= dot(C_y, mpc.L_Hp, C_u)
176184
end
177185
return nothing
178186
end
@@ -187,15 +195,17 @@ Init `ŷ, Ŷop, d0, D̂0` matrices when model is not a [`LinModel`](@ref).
187195
[`InternalModel`](@ref).
188196
"""
189197
function initpred!(mpc::PredictiveController, model::SimModel, d, ym, D̂, R̂y, R̂u)
190-
mpc.[:] = evalŷ(mpc.estim, ym, d)
198+
mpc. .= evalŷ(mpc.estim, ym, d)
191199
predictstoch!(mpc, mpc.estim, d, ym) # init mpc.Ŷop for InternalModel
192200
if model.nd 0
193-
mpc.d0[:], mpc.D̂0[:] = d - model.dop, D̂ - mpc.Dop
194-
mpc.D̂E[:] = [d; D̂]
201+
mpc.d0 .= d .- model.dop
202+
mpc.D̂0 .=.- mpc.Dop
203+
mpc.D̂E[1:model.nd] .= mpc.d0
204+
mpc.D̂E[model.nd+1:end] .= mpc.D̂0
195205
end
196-
mpc.R̂y[:] = R̂y
206+
mpc.R̂y .= R̂y
197207
if ~mpc.noR̂u
198-
mpc.R̂u[:] = R̂u
208+
mpc.R̂u .= R̂u
199209
end
200210
return nothing
201211
end
@@ -214,11 +224,16 @@ function predictstoch!(
214224
) where {NT<:Real}
215225
isnothing(ym) && error("Predictive controllers with InternalModel need the measured "*
216226
"outputs ym in keyword argument to compute control actions u")
217-
ŷd = h(estim.model, estim.x̂d, d - estim.model.dop) + estim.model.yop
227+
Ŷop = mpc.Ŷop
228+
ŷd = h(estim.model, estim.x̂d, d - estim.model.dop) .+ estim.model.yop
218229
ŷs = zeros(NT, estim.model.ny)
219-
ŷs[estim.i_ym] = ym - ŷd[estim.i_ym] # ŷs=0 for unmeasured outputs
220-
Ŷs = mpc.Ks*mpc.estim.x̂s + mpc.Ps*ŷs
221-
mpc.Ŷop[:] = Ŷs + repeat(estim.model.yop, mpc.Hp)
230+
ŷs[estim.i_ym] .= @views ym .- ŷd[estim.i_ym] # ŷs=0 for unmeasured outputs
231+
Ŷop_LHS = similar(Ŷop)
232+
Ŷop .= mul!(Ŷop_LHS, mpc.Ks, estim.x̂s)
233+
Ŷop .+= mul!(Ŷop_LHS, mpc.Ps, ŷs)
234+
for j=1:mpc.Hp
235+
Ŷop[(1 + estim.model.ny*(j-1)):(estim.model.ny*j)] .+= estim.model.yop
236+
end
222237
return nothing
223238
end
224239
"Separate stochastic predictions are not needed if `estim` is not [`InternalModel`](@ref)."
@@ -233,14 +248,18 @@ Also init ``\mathbf{f_x̂} = \mathbf{g_x̂ d}(k) + \mathbf{j_x̂ D̂} + \mathbf{
233248
vector for the terminal constraints, see [`init_predmat`](@ref).
234249
"""
235250
function linconstraint!(mpc::PredictiveController, model::LinModel)
236-
mpc.con.fx̂[:] = mpc.con.kx̂ * mpc.estim.+ mpc.con.vx̂ * mpc.estim.lastu0
251+
fx̂ = mpc.con.fx̂
252+
fx̂_LHS = similar(fx̂)
253+
fx̂ .= mul!(fx̂_LHS, mpc.con.kx̂, mpc.estim.x̂)
254+
fx̂ .+= mul!(fx̂_LHS, mpc.con.vx̂, mpc.estim.lastu0)
237255
if model.nd 0
238-
mpc.con.fx̂[:] = mpc.con.fx̂ + mpc.con.gx̂ * mpc.d0 + mpc.con.jx̂ * mpc.D̂0
256+
fx̂ .+= mul!(fx̂_LHS, mpc.con.gx̂, mpc.d0)
257+
fx̂ .+= mul!(fx̂_LHS, mpc.con.jx̂, mpc.D̂0)
239258
end
240-
lastu = mpc.estim.lastu0 + model.uop
241-
mpc.con.b[:] = [
242-
-mpc.con.Umin + mpc.T*lastu
243-
+mpc.con.Umax - mpc.T*lastu
259+
T_lastu = mpc.T*(mpc.estim.lastu0 .+ model.uop)
260+
mpc.con.b .= [
261+
-mpc.con.Umin + T_lastu
262+
+mpc.con.Umax - T_lastu
244263
-mpc.con.ΔŨmin
245264
+mpc.con.ΔŨmax
246265
-mpc.con.Ymin + mpc.F
@@ -254,10 +273,10 @@ end
254273

255274
"Set `b` excluding predicted output constraints when `model` is not a [`LinModel`](@ref)."
256275
function linconstraint!(mpc::PredictiveController, model::SimModel)
257-
lastu = mpc.estim.lastu0 + model.uop
258-
mpc.con.b[:] = [
259-
-mpc.con.Umin + mpc.T*lastu
260-
+mpc.con.Umax - mpc.T*lastu
276+
T_lastu = mpc.T*(mpc.estim.lastu0 .+ model.uop)
277+
mpc.con.b .= [
278+
-mpc.con.Umin + T_lastu
279+
+mpc.con.Umax - T_lastu
261280
-mpc.con.ΔŨmin
262281
+mpc.con.ΔŨmax
263282
]

src/estimator/kalman.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,15 @@ The [`SteadyKalmanFilter`](@ref) updates it with the precomputed Kalman gain ``\
182182
function update_estimate!(estim::SteadyKalmanFilter, u, ym, d=empty(estim.x̂))
183183
Â, B̂u, B̂d, Ĉm, D̂dm = estim.Â, estim.B̂u, estim.B̂d, estim.Ĉm, estim.D̂dm
184184
x̂, K̂ = estim.x̂, estim.
185-
v̂, x̂LHS = similar(ym), similar(x̂)
185+
v̂, ŷm, x̂LHS = similar(ym), similar(ym), similar(x̂)
186186
# in-place operations to recuce allocations:
187-
v̂ .= ym .- Ĉm*.- D̂dm*d
188-
x̂ .= mul!(x̂LHS, Â, x̂) .+ mul!(x̂LHS, B̂u, u) .+ mul!(x̂LHS, B̂d, d) .+ mul!(x̂LHS, K̂, v̂)
187+
ŷm .= mul!(v̂, Ĉm, x̂)
188+
ŷm .+= mul!(v̂, D̂dm, d)
189+
v̂ .= ym .- ŷm
190+
x̂ .= mul!(x̂LHS, Â, x̂)
191+
.+= mul!(x̂LHS, B̂u, u)
192+
.+= mul!(x̂LHS, B̂d, d)
193+
.+= mul!(x̂LHS, K̂, v̂)
189194
return nothing
190195
end
191196

0 commit comments

Comments
 (0)