@@ -6,62 +6,62 @@ edge cases of automatic differentiation to make it easier for users to get
66high performance even in the cases where code generation may change the
77function that is being called.
88
9- ## dualcache
9+ ## DiffCache
1010
11- ` dualcache ` is a method for generating doubly-preallocated vectors which are
11+ ` DiffCache ` is a method for generating doubly-preallocated vectors which are
1212compatible with non-allocating forward-mode automatic differentiation by
1313ForwardDiff.jl. Since ForwardDiff uses chunked duals in its forward pass, two
1414vector sizes are required in order for the arrays to be properly defined.
15- ` dualcache ` creates a dispatching type to solve this, so that by passing a
15+ ` DiffCache ` creates a dispatching type to solve this, so that by passing a
1616qualifier it can automatically switch between the required cache. This method
1717is fully type-stable and non-dynamic, made for when the highest performance is
1818needed.
1919
20- ### Using dualcache
20+ ### Using DiffCache
2121
2222``` julia
23- dualcache (u:: AbstractArray , N:: Int = ForwardDiff. pickchunksize (length (u)); levels:: Int = 1 )
24- dualcache (u:: AbstractArray , N:: AbstractArray{<:Int} )
23+ DiffCache (u:: AbstractArray , N:: Int = ForwardDiff. pickchunksize (length (u)); levels:: Int = 1 )
24+ DiffCache (u:: AbstractArray , N:: AbstractArray{<:Int} )
2525```
2626
27- The ` dualcache ` function builds a ` DualCache ` object that stores both a version
27+ The ` DiffCache ` function builds a ` DiffCache ` object that stores both a version
2828of the cache for ` u ` and for the ` Dual ` version of ` u ` , allowing use of
2929pre-cached vectors with forward-mode automatic differentiation. Note that
30- ` dualcache ` , due to its design, is only compatible with arrays that contain concretely
30+ ` DiffCache ` , due to its design, is only compatible with arrays that contain concretely
3131typed elements.
3232
3333To access the caches, one uses:
3434
3535``` julia
36- get_tmp (tmp:: DualCache , u)
36+ get_tmp (tmp:: DiffCache , u)
3737```
3838
3939When ` u ` has an element subtype of ` Dual ` numbers, then it returns the ` Dual `
4040version of the cache. Otherwise it returns the standard cache (for use in the
4141calls without automatic differentiation).
4242
43- In order to preallocate to the right size, the ` dualcache ` needs to be specified
44- to have the correct ` N ` matching the chunk size of the dual numbers or larger.
45- If the chunk size ` N ` specified is too large, ` get_tmp ` will automatically resize
46- when dispatching; this remains type-stable and non-allocating, but comes at the
43+ In order to preallocate to the right size, the ` DiffCache ` needs to be specified
44+ to have the correct ` N ` matching the chunk size of the dual numbers or larger.
45+ If the chunk size ` N ` specified is too large, ` get_tmp ` will automatically resize
46+ when dispatching; this remains type-stable and non-allocating, but comes at the
4747expense of additional memory.
4848
4949In a differential equation, optimization, etc., the default chunk size is computed
50- from the state vector ` u ` , and thus if one creates the ` dualcache ` via
51- ` dualcache (u)` it will match the default chunking of the solver libraries.
50+ from the state vector ` u ` , and thus if one creates the ` DiffCache ` via
51+ ` DiffCache (u)` it will match the default chunking of the solver libraries.
5252
53- ` dualcache ` is also compatible with nested automatic differentiation calls through
54- the ` levels ` keyword (` N ` for each level computed using based on the size of the
53+ ` DiffCache ` is also compatible with nested automatic differentiation calls through
54+ the ` levels ` keyword (` N ` for each level computed using based on the size of the
5555state vector) or by specifying ` N ` as an array of integers of chunk sizes, which
5656enables full control of chunk sizes on all differentation levels.
5757
58- ### dualcache Example 1: Direct Usage
58+ ### DiffCache Example 1: Direct Usage
5959
6060``` julia
6161using ForwardDiff, PreallocationTools
6262randmat = rand (5 , 3 )
6363sto = similar (randmat)
64- stod = dualcache (sto)
64+ stod = DiffCache (sto)
6565
6666function claytonsample! (sto, τ, α; randmat= randmat)
6767 sto = get_tmp (sto, τ)
@@ -83,13 +83,13 @@ ForwardDiff.jacobian(x -> claytonsample!(stod, x[1], x[2]), [0.3; 0.0])
8383```
8484
8585In the above, the chunk size of the dual numbers has been selected based on the size
86- of ` randmat ` , resulting in a chunk size of 8 in this case. However, since the derivative
87- is calculated with respect to τ and the Jacobian is calculated with respect to τ and α,
88- specifying the ` dualcache ` with ` stod = dualcache (sto, 1) ` or ` stod = dualcache (sto, 2) ` ,
86+ of ` randmat ` , resulting in a chunk size of 8 in this case. However, since the derivative
87+ is calculated with respect to τ and the Jacobian is calculated with respect to τ and α,
88+ specifying the ` DiffCache ` with ` stod = DiffCache (sto, 1) ` or ` stod = DiffCache (sto, 2) ` ,
8989respectively, would have been the most memory efficient way of performing these calculations
9090(only really relevant for much larger problems).
9191
92- ### dualcache Example 2: ODEs
92+ ### DiffCache Example 2: ODEs
9393
9494``` julia
9595using LinearAlgebra, OrdinaryDiffEq
@@ -115,7 +115,7 @@ function foo(du, u, (A, tmp), t)
115115 nothing
116116end
117117chunk_size = 5
118- prob = ODEProblem (foo, ones (5 , 5 ), (0. , 1.0 ), (ones (5 ,5 ), dualcache (zeros (5 ,5 ), chunk_size)))
118+ prob = ODEProblem (foo, ones (5 , 5 ), (0. , 1.0 ), (ones (5 ,5 ), DiffCache (zeros (5 ,5 ), chunk_size)))
119119solve (prob, TRBDF2 (chunk_size= chunk_size))
120120```
121121
@@ -130,10 +130,10 @@ function foo(du, u, (A, tmp), t)
130130 nothing
131131end
132132chunk_size = 5
133- prob = ODEProblem (foo, ones (5 , 5 ), (0. , 1.0 ), (ones (5 ,5 ), dualcache (zeros (5 ,5 ))))
133+ prob = ODEProblem (foo, ones (5 , 5 ), (0. , 1.0 ), (ones (5 ,5 ), DiffCache (zeros (5 ,5 ))))
134134solve (prob, TRBDF2 ())
135135```
136- ### dualcache Example 3: Nested AD calls in an optimization problem involving a Hessian matrix
136+ ### DiffCache Example 3: Nested AD calls in an optimization problem involving a Hessian matrix
137137
138138``` julia
139139using LinearAlgebra, OrdinaryDiffEq, PreallocationTools, Optim, Optimization
@@ -147,7 +147,7 @@ function foo(du, u, p, t)
147147end
148148
149149coeffs = - collect (0.1 : 0.1 : 0.4 )
150- cache = dualcache (zeros (2 ,2 ), levels = 3 )
150+ cache = DiffCache (zeros (2 ,2 ), levels = 3 )
151151prob = ODEProblem (foo, ones (2 , 2 ), (0. , 1.0 ), (coeffs, cache))
152152realsol = solve (prob, TRBDF2 (), saveat = 0.0 : 0.1 : 10.0 , reltol = 1e-8 )
153153
@@ -160,7 +160,7 @@ function objfun(x, prob, realsol, cache)
160160 ofv = 1e12
161161 else
162162 ofv = sum ((sol.- realsol). ^ 2 )
163- end
163+ end
164164 return ofv
165165end
166166fn (x,p) = objfun (x, p[1 ], p[2 ], p[3 ])
@@ -169,10 +169,29 @@ optprob = OptimizationProblem(optfun, zeros(length(coeffs)), (prob, realsol, cac
169169solve (optprob, Newton ())
170170```
171171Solves an optimization problem for the coefficients, ` coeffs ` , appearing in a differential equation.
172- The optimization is done with [ Optim.jl] ( https://github.com/JuliaNLSolvers/Optim.jl ) 's ` Newton() `
173- algorithm. Since this involves automatic differentiation in the ODE solver and the calculation
174- of Hessians, three automatic differentiations are nested within each other. Therefore, the ` dualcache `
175- is specified with ` levels = 3 ` .
172+ The optimization is done with [ Optim.jl] ( https://github.com/JuliaNLSolvers/Optim.jl ) 's ` Newton() `
173+ algorithm. Since this involves automatic differentiation in the ODE solver and the calculation
174+ of Hessians, three automatic differentiations are nested within each other. Therefore, the ` DiffCache `
175+ is specified with ` levels = 3 ` .
176+
177+ ## FixedSizeDiffCache
178+
179+ ` FixedSizeDiffCache ` is a lot like ` DiffCache ` , but it stores dual numbers in its caches
180+ instead of a flat array. Because of this, it can avoid a view, making it a little bit
181+ more performant for generating caches of non-` Array ` types. However, it is a lot less
182+ flexible than ` DiffCache ` , and is thus only recommended for cases where the chunk size
183+ is known in advance (for example, ODE solvers) and where ` u ` is not an ` Array ` .
184+
185+ The interface is almost exactly the same, except with the constructor:
186+
187+ ``` julia
188+ FixedSizeDiffCache (u:: AbstractArray , chunk_size = Val{ForwardDiff. pickchunksize (length (u))})
189+ FixedSizeDiffCache (u:: AbstractArray , chunk_size:: Integer )
190+ ```
191+
192+ Note that the ` FixedSizeDiffCache ` can support duals that are of a small chunk size than
193+ the preallocated ones, but not a larger size. Nested duals are not supported with this
194+ construct.
176195
177196## LazyBufferCache
178197
@@ -205,7 +224,7 @@ prob = ODEProblem(foo, ones(5, 5), (0., 1.0), (ones(5,5), LazyBufferCache()))
205224solve (prob, TRBDF2 ())
206225```
207226
208- ## Note About ReverseDiff Support for LazyBuffer
227+ ## Note About ReverseDiff Support for LazyBuffer
209228
210229ReverseDiff support is done in SciMLSensitivity.jl to reduce the AD requirements on this package.
211230Load that package if ReverseDiff overloads are required.
@@ -263,7 +282,7 @@ Pkg.status(;mode = PKGMODE_MANIFEST) # hide
263282</details>
264283```
265284``` @raw html
266- You can also download the
285+ You can also download the
267286<a href="
268287```
269288``` @eval
0 commit comments