Skip to content
This repository has been archived by the owner on Apr 18, 2023. It is now read-only.

Add an internal helper function to do more in-place updating #145

Merged
merged 1 commit into from
Apr 13, 2019

Conversation

ararslan
Copy link
Collaborator

Currently the ∇(x̄, f, Arg{N}, args...) method, which updates with the result of ∇(f, Arg{N}, args...), is done in-place for some functions f but not all. In the case of the fallback method, we can use dispatch to determine whether it's safe to do this in-place.

@codecov
Copy link

codecov bot commented Mar 28, 2019

Codecov Report

Merging #145 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #145      +/-   ##
==========================================
+ Coverage   97.04%   97.05%   +<.01%     
==========================================
  Files          20       20              
  Lines         744      746       +2     
==========================================
+ Hits          722      724       +2     
  Misses         22       22
Impacted Files Coverage Δ
src/core.jl 93.47% <100%> (+0.14%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 85b27f7...9c5a84f. Read the comment docs.

Copy link
Contributor

@omus omus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable. Can you add tests for the in-place behaviour?

src/core.jl Outdated Show resolved Hide resolved
@ararslan
Copy link
Collaborator Author

Can you add tests for the in-place behaviour?

I was hoping no one would notice that. :trollface: I couldn't come up with a way to test it that would be sensible from a real-world-code perspective, but I can do something targeted.

@omus
Copy link
Contributor

omus commented Mar 28, 2019

I couldn't come up with a way to test it that would be sensible from a real-world-code perspective, but I can do something targeted.

Sounds good to me. I'd also like to a Nabla expert review this change.

src/core.jl Outdated
@inline ∇(x̄, f, ::Type{Arg{N}}, args...) where {N} = update!(x̄, ∇(f, Arg{N}, args...))

# Use broadcast for mixed array/scalar operations
@inline update!(x̄::∇Scalar, y::∇Array) = x̄ .+ y
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this method isn't covered...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on a conversation with @wesselb, our thinking is that the mixed scalar/array case should not occur and it doing so is indicative of a bug. I'll adjust the definitions here appropriately.

src/core.jl Outdated

# Update arrays in-place. Mixed array and scalar adds should not occur, so don't bother
# accepting scalars on the RHS.
@inline update!(x̄::∇Array, y::∇Array) = x̄ .+= y
Copy link
Collaborator Author

@ararslan ararslan Apr 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized that this is not legit to do in the general case; we'll have to be even more restrictive. Say we have an UpperTriangular stored on the tape. When we go to update this, if we do .+=, the resulting value is still an UpperTriangular, which is wrong. I think updating the value on the tape in-place is only safe when the existing and new values are both Arrays, not AbstractArrays.

@ararslan
Copy link
Collaborator Author

Related to/fixes #61? @willtebbutt

Copy link
Member

@willtebbutt willtebbutt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really nice optimisation. I've left one particular comment that I think needs addressing, but other than that I'm happy. The only other thing we might wish to consider is whether or not to stop force-inlining stuff? I'm honestly not sure why I thought that was a good idea when I first wrote the code.

src/core.jl Outdated Show resolved Hide resolved
Currently the `∇(x̄, f, Arg{N}, args...)` method updates `x̄` with the
result of `∇(f, Arg{N}, args...)`. This is done in-place for some
functions `f` but not all. In the case of the fallback method, we can
use dispatch to determine whether it's safe to do this in-place, thereby
hopefully saving some allocations.
@ararslan
Copy link
Collaborator Author

I've opted to remove the @inline annotations to the newly introduced update! function. Whether to remove them more broadly is out of the scope of this PR, but perhaps an issue to discuss it would be worthwhile.

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

Successfully merging this pull request may close these issues.

3 participants