Enzyme with Const() on a vector throws an error

Hello all,

I would like to autodiff a function where some vector-valued arguments are kept constant. I thought to use Enzyme with the Const() functionality but run into issues when applying Const() to vectors.

The following is a minimal working example that reproduces the problem. I use
Enzyme v0.13.12 with julia 1.11

using Enzyme

# this will work
function f(x::Array{Float64}, c::Vector{Float64})
    y = (x[1]-c[1]) * (x[1]-c[1]) + (x[2]-c[2]) * (x[2]-c[2])
    return y
end;

# this won't work
function h(x::Array{Float64}, c::Vector{Float64})
    y = sum( (x-c).^2 )
    return y
end;

# this will work
function h2(x::Array{Float64}, c1::Float64, c2::Float64)
    c = [c1, c2]
    y = sum( (x-c).^2 )
    return y
end;

The three functions compute the squared norm between the two vectors x and c. For example


x = [4.0, 3.0];
c = [2.0, 1.0];

f(x, c)
f(x, c) == h(x, c) == h2(x, c[1], c[2]) # returns true

Now, autodiff on f and h2 works

dx = [0.0, 0.0]
autodiff(Reverse, f, Active, Duplicated(x, dx), Const(c));
dx
2*(x-c) == dx # true

dx = [0.0, 0.0]
autodiff(Reverse, h2, Active, Duplicated(x, dx), Const(c[1]), Const(c[2]));
dx
2*(x-c) == dx # true

However, for h I get a Constant memory is stored (or returned) to a differentiable variable. error

dx = [0.0, 0.0]
autodiff(Reverse, h, Active, Duplicated(x, dx), Const(c));
dx

I am new to Julia and its AD system and puzzled by this error. It seems to me that Const(c) did not work when c is a vector? What would I need to change to make it work? Manually expanding the vector c into scalars won’t be an option for me.

Many thanks for your help.

I can’t reproduce this on Julia 1.10.6 with Enzyme v0.13.12. Maybe you’re using an older version of Enzyme?

Enzyme on julia 1.11 has some issues still use it on Julia 1.10

1 Like

This seems to be indeed a Julia version issue. The posted code works with Julia 1.10.6, Enzyme v0.13.12 but not with Julia 1.11 (again with Enzyme v0.13.12).

The issue seems to be with the julia version (v 1.11.1) and not the Enzyme version; I was using the same as you. Things indeed work with Julia v 1.10.6. Many thanks for the response.

Yeah Enzyme still has a few things to work out for v1.11

After debugging with @gbaraldi @jameson and @Oscar_Smith, we have found a similar issue to be caused by a performance regression in 1.11.

I believe a fix is in the works (Allow taking Matrix slices without an extra allocation by vtjnash · Pull Request #56236 · JuliaLang/julia · GitHub) and will be subsequently released in a patch of julia 1.11

In particular, 1.11’s new array implementation seems to have caused issues for alias analysis. In particular, julia/base/abstractarray.jl at 9af0dea9d2c7c957bec7a14acacf0b234447be31 · JuliaLang/julia · GitHub causes issues in proving a fresh allocation doesn’t alias with other data.

It’s likely the root cause of your issue above is something similar, so hopefully that fix gets pushed into 1.11 soon.

2 Likes

A workaround has been made to the latest release which enables your case (and simple broadcasting) above to work on 1.11 without runtime activity.

Awesome, thank you for letting me know!