-
-
Notifications
You must be signed in to change notification settings - Fork 46
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
Cache parameters #274
Cache parameters #274
Conversation
That was a bit fiddly to get right (or at least pass the using DataInterpolations
using BenchmarkTools
N = 1000
u = rand(N)
t = cumsum(rand(N))
itp = LinearInterpolation(u, t)
t_eval = range(first(t), last(t), length = 10000)
@btime itp($t_eval)
# old: 162.200 μs (3 allocations: 78.23 KiB)
# new: 119.900 μs (3 allocations: 78.23 KiB) |
Another benchmark: using DataInterpolations
using BenchmarkTools
N = 1000
u = rand(N)
t = cumsum(rand(N))
itp = QuadraticInterpolation(u, t)
@btime DataInterpolations.integral(itp, t[end])
# old: 18.400 μs (3 allocations: 48 bytes)
# new: 9.000 μs (3 allocations: 48 bytes) |
I'll leave it at caching parameters for Interesting ones to cache parameters for next are using DataInterpolations
using BenchmarkTools
N = 1000
u = rand(N)
t = cumsum(rand(N))
t = [0, 62.25, 109.66, 162.66, 205.8, 252.3]
u = [14.7, 11.51, 10.41, 14.95, 12.24, 11.22]
A1 = QuadraticInterpolation(u,t)
A2 = BSplineInterpolation(u, t, 2, :Uniform, :Uniform)
A3 = BSplineApprox(u,t, 2, 4, :Uniform, :Uniform)
ts = collect(range(first(t), last(t), length = 10000))
@btime A1.(ts)
# 91.100 μs (3 allocations: 78.25 KiB)
@btime A2.(ts)
# 394.500 μs (10003 allocations: 1.14 MiB)
@btime A3.(ts)
# 387.400 μs (10003 allocations: 1015.77 KiB) Edit: I made the non-ForwardDiff calls of @btime A2.(ts)
# 250.600 μs (3 allocations: 78.28 KiB)
@btime A3.(ts)
# 244.500 μs (3 allocations: 78.28 KiB) |
Refactor of using DataInterpolations
using BenchmarkTools
N = 10
t = cumsum(rand(N))
u = rand(N)
itp = LagrangeInterpolation(u, t, N-1)
ts = range(first(t), last(t), length = 10000)
@btime itp($ts)
# old: 1.806 ms (20003 allocations: 2.82 MiB)
# new: 465.300 μs (3 allocations: 78.23 KiB) |
Using knowledge of which spline coefficients are non-zero: using DataInterpolations
using BenchmarkTools
t = cumsum(rand(100))
u = rand(100)
A = BSplineInterpolation(u, t, 2, :Uniform, :Uniform)
ts = collect(range(first(t), last(t), length = 10000))
@btime A($ts)
# old: 1.161 ms (2 allocations: 78.17 KiB)
# new: 663.900 μs (2 allocations: 78.17 KiB)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Can you also add a few tests to ensure all cache parameters are set properly?
docs/src/interface.md
Outdated
@@ -35,6 +35,23 @@ A2(300.0) | |||
|
|||
The values computed beyond the range of the time points provided during interpolation will not be reliable, as these methods only perform well within the range and the first/last piece polynomial fit is extrapolated on either side which might not reflect the true nature of the data. | |||
|
|||
The keyword `safetycopy=false` can be passed to make sure no copies of `u` and `t` are made when initializing the interpolation object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to explain why we need safetycopy
push!(di.u, u) | ||
push!(di.t, t) | ||
di | ||
function push!(A::LinearInterpolation{U, T}, u::eltype(U), t::eltype(T)) where {U, T} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be allowed only if safetycopy
is false?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I fully understand the reasoning here. If safetycopy
is true, then the u, t
vectors within the interpolation object can safely be assumed to be only used within the context of this package. Surely then it is safe to add data to it? Only if u, t
are also used in code outside the DataInterpolations
context do you run the risk of breaking that code by modifying u, t
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I understand your point. It comes down what should be the semantics of push!
for interpolation objects. Currently it mutates the original array. Maybe we should handle both cases? If it is true, it would push to the copy, if it is false it would mutate the original array. For both we have to compute the parameters again.
@ChrisRackauckas, your thoughts?
@sathvikbhagavan I made it so that If this is indeed the behavior you want, I still need some help explaining the use of |
docs/src/interface.md
Outdated
u === A3.u.parent | ||
``` | ||
|
||
Note that this does not prevent allocation in every interpolation constructor call, because parameter values are cached for some interpolation types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also add a line describing which interpolations support caching?
src/online.jl
Outdated
push!(di.t, t) | ||
di | ||
function push!(A::LinearInterpolation{U, T}, u::eltype(U), t::eltype(T)) where {U, T} | ||
!A.safetycopy && throw(UnsafeAddDataError()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed? Shouldn't we allow for both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is fine by me, I think it is clear enough that this leads to mutation of the input u, t
if someone explicitly sets safetycopy = false
.
@@ -83,7 +83,7 @@ end | |||
|
|||
@testset "LagrangeInterpolation" begin | |||
u = [1.0, 4.0, 9.0] | |||
t = [1.0, 2.0, 3.0] | |||
t = [1.0, 2.0, 6.0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this function to conveniently test whether the implementation of a new interpolation type is complete: https://github.com/SciML/DataInterpolations.jl/pull/274/files#diff-f66955aae2aee262495ff068999fe35f8501cd1cbef7b1057aa26d2f1099a4f3R6-R17
To do this, I moved throwing an error when integration is not defined from specialised methods of integral
to methods of _integral
. However, that now means that the extrapolation error is thrown before the 'integral not found' error. So, to still test the integral not found error, I had to make sure that the test for this does not try to extrapolate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, that should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there. Just a few cleanups.
@@ -83,7 +83,7 @@ end | |||
|
|||
@testset "LagrangeInterpolation" begin | |||
u = [1.0, 4.0, 9.0] | |||
t = [1.0, 2.0, 3.0] | |||
t = [1.0, 2.0, 6.0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, that should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Nice work! Thanks!
Fixes #271 (the other half)
Checklist
contributor guidelines, in particular the SciML Style Guide and
COLPRAC.
Additional context
Add any other context about the problem here.