-
-
Notifications
You must be signed in to change notification settings - Fork 243
Closed
Description
As noted in the FAQ, using pre-allocated buffers is problematic for automatic differentiation, because then one sometimes needs a buffer of dual numbers instead.
The FAQ suggests using the undocumented get_tmp and dualcache functions. I have to admit that I had a hard time getting these to work in our problem, and the lack of documentation made them somewhat hard to recommend. (A basic difficulty seems to be choosing the right type parameters for the dual numbers ahead of time.)
It occurred to me that a much simpler solution is to allocate buffers lazily, of the same type as u, caching them for later usage. This worked well for us. The implementation is easy — perhaps something like this could be included and suggested in the FAQ?
"""
b = LazyBufferCache(f=identity)
A lazily allocated buffer object. Given a vector `u`, `b[u]` returns a `Vector` of the
same element type and length `f(length(u))` (defaulting to the same length), which is
allocated as needed and then cached within `b` for subsequent usage.
"""
struct LazyBufferCache{F<:Function}
bufs::Dict # a dictionary mapping types to buffers
lengthmap::F
LazyBufferCache(f::F=identity) where {F<:Function} = new{F}(Dict()) # start with empty dict
end
# override the [] method
function Base.getindex(b::LazyBufferCache, u::AbstractVector{T}) where {T}
n = b.lengthmap(length(u)) # required buffer length
buf = get!(b.bufs, T) do
Vector{T}(undef, n) # buffer to allocate if it was not found in b.bufs
end::Vector{T} # declare type since b.bufs dictionary is untyped
return resize!(buf, n) # resize the buffer if needed, e.g. if problem was resized
endMetadata
Metadata
Assignees
Labels
No labels