-
Notifications
You must be signed in to change notification settings - Fork 152
Derivatives using SVector{Dual} #28
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
Comments
Made some other changes to my code, and I think I can confidently state that my only struggle is getting an efficient conversion from For comparison: vector_from_duals{P,N,T}(yp::SVector{P, ForwardDiff.Dual{N,T}}) = map(ForwardDiff.value, yp)
@inbounds function jacobian_from_duals{P,N,T}(yp::SVector{P, ForwardDiff.Dual{N,T}})
SMatrix{P,N}(
ntuple(P*N) do n
i, j = divrem(n-1, N)
ForwardDiff.partials(yp[i+1])[j+1]
end ...
)
end (Note, I've tried several variations of When I time these: julia> @time for i=1:10^5 vector_from_duals(yp) end
0.002037 seconds (100.00 k allocations: 3.052 MB)
julia> @time for i=1:10^5 jacobian_from_duals(yp) end
0.360131 seconds (2.20 M allocations: 51.880 MB, 1.33% gc time) So, I suppose I could write a |
This seems to work well: @generated function jacobian_from_duals{P,N,T}(yp::SVector{P, ForwardDiff.Dual{N,T}})
result = :(SMatrix{P,N}())
for n=1:P*N
i, j = divrem(n-1, N)
p, q = i+1, j+1
term = :(yp[$p].partials[$q])
push!(result.args, term)
end
result
end |
Yes a generated version works well. Your version might not be optimal for large @generated function jacobian_from_duals{P,N,T}(yp::SVector{P, ForwardDiff.Dual{N,T}})
type = SMatrix{P,N}
exprs = [:(yp[$p].partials[$q]) for p = 1:P, n = 1:N]
return quote
$(Expr(:meta, :inline)
@inbounds return $type($(Expr(:tuple, exprs...)))
end
end This should be safe for any |
@dbeach24 by the way, did you see CoordinateTransformations.jl? In there, we have some of the same issues of differential geometry and AD... See JuliaGeometry/CoordinateTransformations.jl#6 for what might be the start of exactly the same conversation. |
Yes, I was secretly excited when I saw what you were working on, @dbeach24. :) |
@dbeach24 did you get what you want here? |
@andyferris Yes, I did. Thanks for the help. |
rename to fieldarrays
@andyferris Thanks for the offer to help. To avoid sabotaging #25, I'm putting my "Jacobian" code in this ticket.
Let's begin with a small, differentiable vector-valued function:
Suppose I want to evaluate this function and its derivative simultaneously, using AD forward mode with dual numbers. Because this is a low-dimensional space, I'd like to use
SVector
/SMatrix
wherever possible.Because the "diagonal" partials can be precomputed and re-used for any low-dimension space, I have moved these to a generated function. The function returns an
MVector
to avoid copying the result on each invocation.Evaluating make_partials is essentially free:
Based on timing tests, calling
eval_jacobian(cart_to_sphere, SVector(1.,2.,3.))
is far more expensive than it could be:If I change
eval_jacobian
to returnyp
(skipping the formation ofy
andJ
), then the timing is substantially better:I think the cost of constructing the Jacobian matrix is the single biggest problem with my code right now.
Ideally, I'd like to see a version with no dynamic allocations (once compiled). Perhaps this will require crafting my own dual-number implementation using
SVector
to hold the partials.Thoughts?
The text was updated successfully, but these errors were encountered: