Skip to content

Commit

Permalink
Merge pull request #111 from SouthEndMusic/LBC_initializer
Browse files Browse the repository at this point in the history
Add optional `initializer!` function to `LazyBufferCache`
  • Loading branch information
ChrisRackauckas authored Jul 31, 2024
2 parents 36263af + f89d012 commit 20791bc
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 4 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ A `LazyBufferCache` is a `Dict`-like type for the caches which automatically def
new cache arrays on demand when they are required. The function `f` maps
`size_of_cache = f(size(u))`, which by default creates cache arrays of the same size.

By default the created buffers are not initialized, but a function `initializer!`
can be supplied which is applied to the buffer when it is created, for instance `buf -> fill!(buf, 0.0)`.

Note that `LazyBufferCache` is type-stable and contains no dynamic dispatch. This gives
it a ~15ns overhead. The upside of `LazyBufferCache` is that the user does not have to
worry about potential issues with chunk sizes and such: `LazyBufferCache` is much easier!
Expand Down
3 changes: 3 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ A `LazyBufferCache` is a `Dict`-like type for the caches, which automatically de
new cache arrays on demand when they are required. The function `f` maps
`size_of_cache = f(size(u))`, which by default creates cache arrays of the same size.

By default the created buffers are not initialized, but a function `initializer!`
can be supplied which is applied to the buffer when it is created, for instance `buf -> fill!(buf, 0.0)`.

Note that `LazyBufferCache` is type-stable and contains no dynamic dispatch. This gives
it a ~15ns overhead. The upside of `LazyBufferCache` is that the user does not have to
worry about potential issues with chunk sizes and such: `LazyBufferCache` is much easier!
Expand Down
18 changes: 14 additions & 4 deletions src/PreallocationTools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -197,19 +197,27 @@ end
# LazyBufferCache

"""
b = LazyBufferCache(f=identity)
b = LazyBufferCache(f = identity; initializer! = identity)
A lazily allocated buffer object. Given an array `u`, `b[u]` returns an array of the
same type and size `f(size(u))` (defaulting to the same size), which is allocated as
needed and then cached within `b` for subsequent usage.
By default the created buffers are not initialized, but a function `initializer!`
can be supplied which is applied to the buffer when it is created, for instance `buf -> fill!(buf, 0.0)`.
Optionally, the size can be explicitly given at calltime using `b[u,s]`, which will
return a cache of size `s`.
"""
struct LazyBufferCache{F <: Function}
struct LazyBufferCache{F <: Function, I <: Function}
bufs::Dict{Any, Any} # a dictionary mapping (type, size) pairs to buffers
sizemap::F
LazyBufferCache(f::F = identity) where {F <: Function} = new{F}(Dict(), f) # start with empty dict
initializer!::I
function LazyBufferCache(
f::F = identity; initializer!::I = identity) where {
F <: Function, I <: Function}
new{F, I}(Dict(), f, initializer!)
end # start with empty dict
end

similar_type(x::AbstractArray, s::Integer) = similar_type(x, (s,))
Expand All @@ -222,7 +230,9 @@ end
function get_tmp(
b::LazyBufferCache, u::T, s = b.sizemap(size(u))) where {T <: AbstractArray}
get!(b.bufs, (T, s)) do
similar(u, s) # buffer to allocate if it was not found in b.bufs
buffer = similar(u, s) # buffer to allocate if it was not found in b.bufs
b.initializer!(buffer)
buffer
end::similar_type(u, s) # declare type since b.bufs dictionary is untyped
end

Expand Down
6 changes: 6 additions & 0 deletions test/lbc.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using PreallocationTools: LazyBufferCache
using Test

b = LazyBufferCache(Returns(10); initializer! = buf -> fill!(buf, 0))

@test b[Float64[]] == zeros(10)
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ if GROUP == "All" || GROUP == "Core"
@safetestset "DiffCache Resizing" include("core_resizing.jl")
@safetestset "DiffCache Nested Duals" include("core_nesteddual.jl")
@safetestset "DiffCache Sparsity Support" include("sparsity_support.jl")
@safetestset "LazyBufferCache" include("lbc.jl")
@safetestset "GeneralLazyBufferCache" include("general_lbc.jl")
end

Expand Down

0 comments on commit 20791bc

Please sign in to comment.