Skip to content

Commit 53ebab8

Browse files
Avoid wide Enzyme batches for Lagrangian Hessians
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://chatgpt.com/codex/tasks/01a03a17-ad6f-7131-82fc-d0fd57ea6512
1 parent 3d24b3f commit 53ebab8

3 files changed

Lines changed: 74 additions & 32 deletions

File tree

lib/OptimizationBase/ext/OptimizationEnzymeExt.jl

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -456,23 +456,29 @@ function OptimizationBase.instantiate_function(
456456
lag_vdbθ = Tuple((copy(r) for r in eachrow(f.hess_prototype)))
457457
end
458458

459-
function lag_h!(h, θ, σ, μ, p = p)
460-
Enzyme.make_zero!(lag_bθ)
461-
Enzyme.make_zero!.(lag_vdbθ)
459+
function fill_lag_hessian!(θ, σ, μ, p)
460+
for i in eachindex(θ)
461+
Enzyme.make_zero!(lag_bθ)
462+
Enzyme.make_zero!(lag_vdbθ[i])
463+
Enzyme.autodiff(
464+
fmode,
465+
lag_grad,
466+
Const(rmode),
467+
Enzyme.Duplicated(θ, lag_vdθ[i]),
468+
Enzyme.DuplicatedNoNeed(lag_bθ, lag_vdbθ[i]),
469+
Const(lagrangian),
470+
Const(f.f),
471+
Const(f.cons),
472+
Const(p),
473+
Const(σ),
474+
Const(μ)
475+
)
476+
end
477+
return nothing
478+
end
462479

463-
Enzyme.autodiff(
464-
fmode,
465-
lag_grad,
466-
Const(rmode),
467-
Enzyme.BatchDuplicated(θ, lag_vdθ),
468-
Enzyme.BatchDuplicatedNoNeed(lag_bθ, lag_vdbθ),
469-
Const(lagrangian),
470-
Const(f.f),
471-
Const(f.cons),
472-
Const(p),
473-
Const(σ),
474-
Const(μ)
475-
)
480+
function lag_h!(h, θ, σ, μ, p = p)
481+
fill_lag_hessian!(θ, σ, μ, p)
476482
k = 0
477483

478484
for i in eachindex(θ)
@@ -485,22 +491,7 @@ function OptimizationBase.instantiate_function(
485491

486492
function lag_h!(H::AbstractMatrix, θ, σ, μ, p = p)
487493
Enzyme.make_zero!(H)
488-
Enzyme.make_zero!(lag_bθ)
489-
Enzyme.make_zero!.(lag_vdbθ)
490-
491-
Enzyme.autodiff(
492-
fmode,
493-
lag_grad,
494-
Const(rmode),
495-
Enzyme.BatchDuplicated(θ, lag_vdθ),
496-
Enzyme.BatchDuplicatedNoNeed(lag_bθ, lag_vdbθ),
497-
Const(lagrangian),
498-
Const(f.f),
499-
Const(f.cons),
500-
Const(p),
501-
Const(σ),
502-
Const(μ)
503-
)
494+
fill_lag_hessian!(θ, σ, μ, p)
504495

505496
for i in eachindex(θ)
506497
H[i, :] .= lag_vdbθ[i]
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using ChainRulesCore, Enzyme, OptimizationBase, Test
2+
3+
function check_lagrangian_hessian(N)
4+
h = 1 / N
5+
alpha = 350
6+
x_offset = N + 1
7+
u_offset = 2(N + 1)
8+
function objective(x, p)
9+
return sum(
10+
0.5 * h * (x[u_offset + i + 1]^2 + x[u_offset + i]^2) +
11+
0.5 * alpha * h * (cos(x[i + 1]) + cos(x[i])) for i in 1:N
12+
) + x[1] * x[2]
13+
end
14+
function constraint!(res, x, p)
15+
for i in 1:N
16+
res[i] = x[x_offset + i + 1] - x[x_offset + i] -
17+
0.5 * h * (sin(x[i + 1]) + sin(x[i]))
18+
res[N + i] = x[i + 1] - x[i] -
19+
0.5 * h * (x[u_offset + i + 1] + x[u_offset + i])
20+
end
21+
return nothing
22+
end
23+
24+
x = zeros(3(N + 1))
25+
f = OptimizationFunction(objective, AutoEnzyme(); cons = constraint!)
26+
instantiated = OptimizationBase.instantiate_function(
27+
f, x, AutoEnzyme(), nothing, 2N; lag_h = true
28+
)
29+
multipliers = ones(2N)
30+
expected = zeros(length(x), length(x))
31+
for i in 1:(N + 1)
32+
expected[i, i] = (i == 1 || i == N + 1) ? -0.5alpha * h : -alpha * h
33+
expected[u_offset + i, u_offset + i] =
34+
(i == 1 || i == N + 1) ? h : 2h
35+
end
36+
expected[1, 2] = expected[2, 1] = 1
37+
38+
packed = zeros(length(x) * (length(x) + 1) ÷ 2)
39+
instantiated.lag_h(packed, x, 1.0, multipliers)
40+
@test packed [expected[i, j] for i in axes(expected, 1) for j in 1:i]
41+
42+
dense = zeros(length(x), length(x))
43+
instantiated.lag_h(dense, x, 1.0, multipliers)
44+
@test dense expected
45+
return nothing
46+
end
47+
48+
@testset "Enzyme Lagrangian Hessian" begin
49+
foreach(check_lagrangian_hessian, (1:10..., 20, 40, 60))
50+
end

lib/OptimizationBase/test/AD/tests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Test
22

33
@testset "OptimizationBase AD" begin
4+
include("enzyme_lagrangian_hessian.jl")
45
include("adtests.jl")
56
include("dual_tolerant_tests.jl")
67
include("cvxtest.jl")

0 commit comments

Comments
 (0)