Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic derivatives of SLEEF trig functions cause stack-overflow #11

Open
MasonProtter opened this issue Sep 25, 2018 · 7 comments
Open

Comments

@MasonProtter
Copy link

MasonProtter commented Sep 25, 2018

Not sure if this is a SLEEF problem for a ForwardDiff problem but I would have expected a different error than a stack overflow when trying to take automatic derivatives of SLEEF trig functions.

julia> using ForwardDiff: derivative

julia> using SLEEF

julia> derivative(SLEEF.sin, 1.0)
ERROR: StackOverflowError:
Stacktrace:
 [1] sin(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(SLEEF.sin),Float64},Float64,1}) at
/Users/mason/.julia/packages/SLEEF/pKpdp/src/SLEEF.jl:105 (repeats 80000 times)

Note: defining the action of trig functions on ForwardDiff.Duals does give the correct behaviour.

julia> using ForwardDiff: derivative, Dual, value, partials

julia> using SLEEF

julia> SLEEF.sin(d::Dual{T,V,N}) where {T,V,N} = Dual{T,V,N}(SLEEF.sin(value(d)), SLEEF.cos(value(d)) * partials(d))

julia> derivative(SLEEF.sin, 3.14)
-0.9999987317275395
@musm
Copy link
Owner

musm commented Sep 25, 2018

can you try sin_fast ? (the fast trig function doesn't use a DualNumber wrapper, which may be causing the stack overflow)

@MasonProtter
Copy link
Author

MasonProtter commented Sep 25, 2018

julia> using ForwardDiff: derivative

julia> using SLEEF

julia> derivative(SLEEF.sin_fast, 1.0)
ERROR: StackOverflowError:
Stacktrace:
 [1] sin_fast(::Dual{ForwardDiff.Tag{typeof(SLEEF.sin_fast),Float64},Float64,1}) at 
/Users/mason/.julia/packages/SLEEF/pKpdp/src/SLEEF.jl:105 (repeats 80000 times)

@tkoolen
Copy link

tkoolen commented Sep 25, 2018

Ref JuliaLang/julia#26552, particularly JuliaLang/julia#26552 (comment).

@musm
Copy link
Owner

musm commented Sep 27, 2018

Ok thanks @tkoolen , it seems that this can be improved.

@musm
Copy link
Owner

musm commented Oct 10, 2018

So I guess the best way of going about this is something like the following?

using ForwardDiff: derivative

f(x::Union{Float32,Float64}) = exp(x)
for func in (:f,)
    priv = Symbol('_',func)
    @eval begin
    $priv(x::T) where {T<:Union{Float32,Float64}} = $func(x)
    $func(x::Real) = $priv(float(x))
    end
end

julia> derivative(f, 1.0)
ERROR: MethodError: no method matching _f(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(f),Float64},Float64,1})

altough it's not clear to my why forwarddiff doesn't work without a custom wrapper.

@musm
Copy link
Owner

musm commented Oct 10, 2018

I was puzzeled as to why the base math function worked with ForwardDiff, but now I see that ForwardDiff relies on DiffRules to be able to differentiate the base math functions.

In principle it should be able to support SLEEF, ideally without having to add anything to DiffRules, but I am not sure how to do that.

@robsmith11
Copy link

robsmith11 commented May 7, 2020

Is this the same reason SLEEF functions don't work with Zygote?

julia> Zygote.gradient(SLEEF.exp, 1.3)                                      
ERROR: Non-differentiable function Core.Intrinsics.bitcast

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants