Enzyme.jl icon indicating copy to clipboard operation
Enzyme.jl copied to clipboard

Enzyme fails to differentiate where Zygote succeeds: `jl_get_builtin_fptr`

Open FriesischScott opened this issue 6 months ago • 10 comments

I ran into an issue optimizing hyper parameters of a Gaussian process with Optim and Enzyme. I'm using AbstractGPs and ParameterHandling in my objective function. I have solved this problem with Zygote so it should be differentiable.

Using AutoZygote() with Optim suggests to either set

autodiff=AutoEnzyme(; mode=Enzyme.set_runtime_activity(Enzyme.Forward))

or

autodiff=AutoEnzyme(; mode=Enzyme.set_runtime_activity(Enzyme.Reverse))

which fail with

ERROR: Enzyme.Compiler.EnzymeNoDerivativeError(Cstring(0x00007f4605d3885c))
Stacktrace:
  [1] _similar_for
    @ ./array.jl:670 [inlined]
  [2] _collect
    @ ./array.jl:816
  [3] collect_similar
    @ ./array.jl:720 [inlined]
  [4] map
    @ ./abstractarray.jl:3371 [inlined]
  [5] value
    @ ~/.julia/packages/ParameterHandling/WkHof/src/parameters_base.jl:17 [inlined]
  [6] fwddiffe4julia_value_32851wrap
    @ ~/.julia/packages/ParameterHandling/WkHof/src/parameters_base.jl:0
  [7] macro expansion
    @ ~/.julia/packages/Enzyme/Qi7lx/src/compiler.jl:5493 [inlined]
  [8] enzyme_call
    @ ~/.julia/packages/Enzyme/Qi7lx/src/compiler.jl:5027 [inlined]
  [9] ForwardModeThunk
    @ ~/.julia/packages/Enzyme/Qi7lx/src/compiler.jl:4918 [inlined]
 [10] runtime_generic_fwd(activity::Type{…}, runtimeActivity::Val{…}, strongZero::Val{…}, width::Val{…}, RT::Val{…}, f::typeof(ParameterHandling.value), df::Nothing, df_2::Nothing, df_3::Nothing, df_4::Nothing, primal_1::Vector{…}, shadow_1_1::Vector{…}, shadow_1_2::Vector{…}, shadow_1_3::Vector{…}, shadow_1_4::Vector{…})
    @ Enzyme.Compiler ~/.julia/packages/Enzyme/Qi7lx/src/rules/jitrules.jl:327
 [11] f
    @ ~/enzyme-issue/main.jl:25 [inlined]
 [12] fwddiffe4julia_f_17712wrap
    @ ~/enzyme-issue/main.jl:0
 [13] macro expansion
    @ ~/.julia/packages/Enzyme/Qi7lx/src/compiler.jl:5493 [inlined]
 [14] enzyme_call
    @ ~/.julia/packages/Enzyme/Qi7lx/src/compiler.jl:5027 [inlined]
 [15] ForwardModeThunk
    @ ~/.julia/packages/Enzyme/Qi7lx/src/compiler.jl:4918 [inlined]
 [16] autodiff
    @ ~/.julia/packages/Enzyme/Qi7lx/src/Enzyme.jl:669 [inlined]
 [17] autodiff
    @ ~/.julia/packages/Enzyme/Qi7lx/src/Enzyme.jl:538 [inlined]
 [18] macro expansion
    @ ~/.julia/packages/Enzyme/Qi7lx/src/sugar.jl:726 [inlined]
 [19] #gradient#112
    @ ~/.julia/packages/Enzyme/Qi7lx/src/sugar.jl:582 [inlined]
 [20] value_and_gradient
    @ ~/.julia/packages/DifferentiationInterface/alBlj/ext/DifferentiationInterfaceEnzymeExt/forward_onearg.jl:186 [inlined]
 [21] value_and_gradient!(::typeof(f), ::Vector{…}, ::DifferentiationInterfaceEnzymeExt.EnzymeForwardGradientPrep{…}, ::AutoEnzyme{…}, ::Vector{…})
    @ DifferentiationInterfaceEnzymeExt ~/.julia/packages/DifferentiationInterface/alBlj/ext/DifferentiationInterfaceEnzymeExt/forward_onearg.jl:213
 [22] (::NLSolversBase.var"#fg!#14"{…})(_g::Vector{…}, _x::Vector{…})
    @ NLSolversBase ~/.julia/packages/NLSolversBase/n7XXO/src/objective_types/oncedifferentiable.jl:53
 [23] value_gradient!!(obj::OnceDifferentiable{Float64, Vector{Float64}, Vector{Float64}}, x::Vector{Float64})
    @ NLSolversBase ~/.julia/packages/NLSolversBase/n7XXO/src/interface.jl:82
 [24] initial_state(method::LBFGS{…}, options::Optim.Options{…}, d::OnceDifferentiable{…}, initial_x::Vector{…})
    @ Optim ~/.julia/packages/Optim/7krni/src/multivariate/solvers/first_order/l_bfgs.jl:168
 [25] optimize
    @ ~/.julia/packages/Optim/7krni/src/multivariate/optimize/optimize.jl:43 [inlined]
 [26] #optimize#77
    @ ~/.julia/packages/Optim/7krni/src/multivariate/optimize/interface.jl:274 [inlined]
 [27] optimize
    @ ~/.julia/packages/Optim/7krni/src/multivariate/optimize/interface.jl:264 [inlined]
 [28] top-level scope
    @ ~/enzyme-issue/main.jl:42

Executing again in the same REPL session changes the error message to

ERROR: 
No augmented forward pass found for jl_get_builtin_fptr
 at context:   %47 = call {} addrspace(10)* ({} addrspace(10)*, {} addrspace(10)**, i32)* @jl_get_builtin_fptr({} addrspace(10)* noundef addrspacecast ({}* inttoptr (i64 140689697642928 to {}*) to {} addrspace(10)*)) #19, !dbg !95

I've setup a small repository to reproduce the error here: https://github.com/FriesischScott/enzyme-issue

FriesischScott avatar Jun 18 '25 08:06 FriesischScott

I'm pinging @gdalle because we discussed this already on slack.

FriesischScott avatar Jun 18 '25 08:06 FriesischScott

Thanks! I'll try to cook up a minimum working example that doesn't call DifferentiationInterface, to see if the error persists

gdalle avatar Jun 18 '25 08:06 gdalle

Would also be good to figure out why the error printing is messed up ERROR: Enzyme.Compiler.EnzymeNoDerivativeError(Cstring(0x00007f4605d3885c))

vchuravy avatar Jun 18 '25 08:06 vchuravy

Here's an MWE without DI or Optim:

using Enzyme
using ParameterHandling
using AbstractGPs
using StatsBase

x = [
    -5.0 -3.5714285714285716 -2.1428571428571432 -0.7142857142857144 0.7142857142857135 2.1428571428571432 3.571428571428571 5.0 -5.0 -3.5714285714285716 -2.1428571428571432 -0.7142857142857144 0.7142857142857135 2.1428571428571432 3.571428571428571 5.0 -5.0 -3.5714285714285716 -2.1428571428571432 -0.7142857142857144 0.7142857142857135 2.1428571428571432 3.571428571428571 5.0 -5.0 -3.5714285714285716 -2.1428571428571432 -0.7142857142857144 0.7142857142857135 2.1428571428571432 3.571428571428571 5.0 -5.0 -3.5714285714285716 -2.1428571428571432 -0.7142857142857144 0.7142857142857135 2.1428571428571432 3.571428571428571 5.0 -5.0 -3.5714285714285716 -2.1428571428571432 -0.7142857142857144 0.7142857142857135 2.1428571428571432 3.571428571428571 5.0 -5.0 -3.5714285714285716 -2.1428571428571432 -0.7142857142857144 0.7142857142857135 2.1428571428571432 3.571428571428571 5.0 -5.0 -3.5714285714285716 -2.1428571428571432 -0.7142857142857144 0.7142857142857135 2.1428571428571432 3.571428571428571 5.0
    -5.0 -5.0 -5.0 -5.0 -5.0 -5.0 -5.0 -5.0 -3.5714285714285716 -3.5714285714285716 -3.5714285714285716 -3.5714285714285716 -3.5714285714285716 -3.5714285714285716 -3.5714285714285716 -3.5714285714285716 -2.1428571428571432 -2.1428571428571432 -2.1428571428571432 -2.1428571428571432 -2.1428571428571432 -2.1428571428571432 -2.1428571428571432 -2.1428571428571432 -0.7142857142857144 -0.7142857142857144 -0.7142857142857144 -0.7142857142857144 -0.7142857142857144 -0.7142857142857144 -0.7142857142857144 -0.7142857142857144 0.7142857142857135 0.7142857142857135 0.7142857142857135 0.7142857142857135 0.7142857142857135 0.7142857142857135 0.7142857142857135 0.7142857142857135 2.1428571428571432 2.1428571428571432 2.1428571428571432 2.1428571428571432 2.1428571428571432 2.1428571428571432 2.1428571428571432 2.1428571428571432 3.571428571428571 3.571428571428571 3.571428571428571 3.571428571428571 3.571428571428571 3.571428571428571 3.571428571428571 3.571428571428571 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0
]
y = [
    250.0
    218.7130362349021
    381.5951686797168
    538.7296959600167
    590.1582673885882
    535.880882965431
    475.8558933777592
    610.0
    109.32528113286128
    8.06747188671387
    112.64056643065388
    223.1278633902541
    239.57101207830073
    161.97001249479385
    90.28321532694711
    224.42732194918779
    195.47271970012494
    35.90587255310287
    93.83173677634318
    169.33361099541855
    162.4531445231154
    73.19033735943356
    1.5035401915868438
    147.3094543940025
    308.52561432736354
    102.31153685964182
    125.25197834235732
    177.43023740108288
    158.88796334860479
    69.62515618492293
    9.60016659725114
    178.72969596001664
    348.52561432736366
    107.32611411911704
    106.94294044148275
    147.45939192003337
    128.91711786755522
    51.316118284048315
    14.614743856726365
    218.7296959600167
    315.4727197001249
    50.94960433152854
    38.904623073719264
    79.42107455226987
    72.54060807996669
    18.26322365680965
    16.547271970012485
    267.3094543940025
    309.3252811328612
    33.14035818408996
    21.0953769262807
    73.27363598500622
    89.7167846730529
    70.42482299042062
    115.35610162432312
    424.4273219491878
    530.0
    253.8150770512286
    253.43190337359434
    328.9337775926697
    380.36234902124124
    407.71761765930864
    510.95793419408574
    890.0
]

transform = fit(ZScoreTransform, y; dims=1)
y = StatsBase.transform(transform, y)

n = ParameterHandling.positive(1e-5, exp, 1e-6)

t = ParameterHandling.positive([1.0, 1.0])

θ₀, unflatten = ParameterHandling.flatten([t, n])

θ₀ = [0.0, θ₀...]

function f(θ)
    θ_u = ParameterHandling.value(unflatten(θ[2:end]))
    kernel = SqExponentialKernel() ∘ ARDTransform(θ_u[1])
    gp = GP(θ[1], kernel)
    return -logpdf(gp(x, θ_u[2]), y)[1]
end

Enzyme.gradient(Enzyme.set_runtime_activity(Enzyme.Reverse), f, θ₀)
julia> Enzyme.gradient(Enzyme.set_runtime_activity(Enzyme.Reverse), f, θ₀)
ERROR: 
No augmented forward pass found for jl_get_builtin_fptr
 at context:   %47 = call {} addrspace(10)* ({} addrspace(10)*, {} addrspace(10)**, i32)* @jl_get_builtin_fptr({} addrspace(10)* noundef addrspacecast ({}* inttoptr (i64 5119221792 to {}*) to {} addrspace(10)*)) #19, !dbg !95

Stacktrace:
 [1] _similar_for
   @ ./array.jl:670
 [2] _collect
   @ ./array.jl:816


Stacktrace:
  [1] _similar_for
    @ ./array.jl:670 [inlined]

gdalle avatar Jun 30 '25 13:06 gdalle

A similar error occurs in forward-over-forward:

julia> using DifferentiationInterface

julia> import Enzyme

julia> hvp(
           sum,
           SecondOrder(AutoEnzyme(; mode=Enzyme.Forward), AutoEnzyme(; mode=Enzyme.Forward)),
           [1.0],
           ([1.0],),
       )
ERROR: 
No forward mode derivative found for jl_get_builtin_fptr
 at context:   %10 = call {} addrspace(10)* ({} addrspace(10)*, {} addrspace(10)**, i32)* @jl_get_builtin_fptr({} addrspace(10)* noundef addrspacecast ({}* inttoptr (i64 4725148592 to {}*) to {} addrspace(10)*)) #14, !dbg !38

Stacktrace:
 [1] make_context_shadows
   @ ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/ext/DifferentiationInterfaceEnzymeExt/utils.jl:99
 [2] prepare_gradient_nokwarg
   @ ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/ext/DifferentiationInterfaceEnzymeExt/forward_onearg.jl:151


Stacktrace:
  [1] make_context_shadows
    @ ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/ext/DifferentiationInterfaceEnzymeExt/utils.jl:99 [inlined]
  [2] prepare_gradient_nokwarg
    @ ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/ext/DifferentiationInterfaceEnzymeExt/forward_onearg.jl:151
  [3] gradient
    @ ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/src/first_order/gradient.jl:62
  [4] shuffled_gradient
    @ ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/src/first_order/gradient.jl:160 [inlined]
  [5] fwddiffejulia_shuffled_gradient_360996wrap
    @ ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/src/first_order/gradient.jl:0
  [6] macro expansion
    @ ~/.julia/packages/Enzyme/HWLY7/src/compiler.jl:5717 [inlined]
  [7] enzyme_call
    @ ~/.julia/packages/Enzyme/HWLY7/src/compiler.jl:5251 [inlined]
  [8] ForwardModeThunk
    @ ~/.julia/packages/Enzyme/HWLY7/src/compiler.jl:5153 [inlined]
  [9] autodiff
    @ ~/.julia/packages/Enzyme/HWLY7/src/Enzyme.jl:669 [inlined]
 [10] autodiff
    @ ~/.julia/packages/Enzyme/HWLY7/src/Enzyme.jl:558 [inlined]
 [11] autodiff
    @ ~/.julia/packages/Enzyme/HWLY7/src/Enzyme.jl:530 [inlined]
 [12] pushforward
    @ ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/ext/DifferentiationInterfaceEnzymeExt/forward_onearg.jl:76 [inlined]
 [13] hvp
    @ ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/src/second_order/hvp.jl:331 [inlined]
 [14] hvp(::typeof(sum), ::SecondOrder{AutoEnzyme{…}, AutoEnzyme{…}}, ::Vector{Float64}, ::Tuple{Vector{…}})
    @ DifferentiationInterface ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/src/second_order/hvp.jl:75
 [15] top-level scope
    @ ~/Documents/GitHub/Julia/DifferentiationInterface.jl/DifferentiationInterface/test/Back/Enzyme/playground.jl:37
Some type information was truncated. Use `show(err)` to see complete types.

gdalle avatar Sep 29 '25 15:09 gdalle

can this be isolated to just calls to autodiff (and as isolated to Enzyme as possible)?

wsmoses avatar Sep 29 '25 16:09 wsmoses

This one is a bit trickier to extract because the Enzyme error happens in the DI machinery surrounding context management, not in differentiation per se. I just put it here so that there would be a trace, I'll try to boil it down some day soon

gdalle avatar Sep 29 '25 16:09 gdalle

understood, but this error specifically seems to come from julia compiler specific choice of type instabilities. So having the exact code to reproduce it is helpful (and also narrowing down may help DI + Enzyme be faster and/or better supported in general)

wsmoses avatar Sep 29 '25 16:09 wsmoses

gently ping @gdalle

wsmoses avatar Nov 07 '25 07:11 wsmoses

Sorry, it's unlikely I'll have time to get to it soon

gdalle avatar Nov 07 '25 22:11 gdalle