这是indexloc提供的服务,不要输入任何密码
Skip to content

Enzyme gradient example broken #2554

@lassepe

Description

@lassepe

Following the Enzyme.jl example:

using Flux: Flux
using Enzyme: Enzyme

function reproducer()
    model = Flux.Chain(Flux.Dense(28^2 => 32, Flux.sigmoid), Flux.Dense(32 => 10), Flux.softmax)
    # this allocates space for the gradient
    model_shadow = Enzyme.Duplicated(model)
    input = randn(28^2, 1)
    label = [i == 3 for i in 1:10]
    grad_model = Flux.gradient(
        (m, x, y) -> sum(abs2, m(x) .- y),
        model_shadow,
        # input and label are const because we differentiate w.r.t. to the model parameters, not input or output.
        Enzyme.Const(input),
        Enzyme.Const(label),
    )
end

reproducer()

I run into the following error both on Julia 1.10.7 and Julia 1.11.2

ERROR: Constant memory is stored (or returned) to a differentiable variable.
As a result, Enzyme cannot provably ensure correctness and throws this error.
This might be due to the use of a constant variable as temporary storage for active memory (https://enzyme.mit.edu/julia/stable/faq/#Runtime-Activity).
If Enzyme should be able to prove this use non-differentable, open an issue!
To work around this issue, either:
 a) rewrite this variable to not be conditionally active (fastest, but requires a code change), or
 b) set the Enzyme mode to turn on runtime activity (e.g. autodiff(set_runtime_activity(Reverse), ...) ). This will maintain correctness, but may slightly reduce performance.
Mismatched activity for:   store {} addrspace(10)* %68, {} addrspace(10)* addrspace(10)* %.repack65, align 8, !dbg !331, !tbaa !333, !alias.scope !268, !noalias !335 const val:   %68 = call fastcc nonnull {} addrspace(10)* @julia_summary_3629({} addrspace(10)* nocapture nofree noundef nonnull readonly align 16 dereferenceable(40) %1) #308, !dbg !323
Type tree: {[-1]:Pointer}
 llvalue=  %68 = call fastcc nonnull {} addrspace(10)* @julia_summary_3629({} addrspace(10)* nocapture nofree noundef nonnull readonly align 16 dereferenceable(40) %1) #308, !dbg !323

Stacktrace:
 [1] #invokelatest#2
   @ ./essentials.jl:894
 [2] invokelatest
   @ ./essentials.jl:889
 [3] macro expansion
   @ ./logging.jl:377
 [4] _match_eltype
   @ ~/.julia/packages/Flux/fteq2/src/layers/stateless.jl:60

Interestingly, each of the following changes resolves the issue:

  1. Calling the gradient computation as Enzyme.gradient(Enzyme.set_runtime_activity(Enzyme.Reverse), ...) as suggested by the error messages works.
  2. Explicitly converting input to Float32 before passing it to Flux.gradient also resolves the issue

However, it seems that the conversion to Float32 alone is not the culprit. The following works as expected:

function sum_converted(x)
    sum(convert(AbstractArray{Float32}, x))
end

function reproducer_reduced()
    input = randn(10)
    Enzyme.gradient(Enzyme.Reverse, sum_converted, input)
end
# returns `([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],)`

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions