Performance Tips
The following tips are meant to decrease the derivative computation's runtime complexity, especially when derivatives of the same function are needed repeatedly. There are two major modifications for all kinds of derivatives:
- Use the
derivative!driver, and work withallocatoras explained in the guide Working with C++ Memory - Reuse the tape as often as possible.
derivative!(derivative) supply the flagreuse_tape, which if set totruesuppresses the creation of the tape, in addition the identifiyer of an existing tape must be provided as the parametertape_id. More details can be found here.
An example could look like this:
using ADOLC # hide
# problem setup
f(x) = (x[1] - x[2])^2
x = [3.0, 7.5]
dir = [1/3, 1/7]
m = 1
n = 2
mode = :jac_vec
num_dir = size(dir, 2)[1]
num_weights = 0
tape_id = 1
num_iters = 100
# pre-allocation
cxx_res = allocator(m, n, mode, num_dir, num_weights)
derivative!(cxx_res, f, m, n, x, mode, dir=dir, tape_id=tape_id)
# conversion
# do computations ....
for i in 1:num_iters
# update x ...
derivative!(cxx_res, f, m, n, x, mode, dir=dir, tape_id=tape_id, reuse_tape=true)
# do computations ...
endMoreover, for higher-order derivatives you might consider the generation of a seed. However, if you do not pass a seed to the derivative! (derivative) driver, the partial identity is created as the seed automatically (see here).