Removing allocations from ForwardDiff.jacobian!

I’m getting a few stray allocations while using ForwardDiff.jacobian!. I followed the advice in this post, but that didn’t seem to remove them. What’s the best way to track down and eliminate these allocations?

Edit: I’m using Julia v1.7.2. OS is Ubuntu 20.04.

MWE:

using ForwardDiff, BenchmarkTools

# Functions
function func(dx,x)::Nothing
  @. dx = 2*x
  return nothing
end

function jac!(J,dx,x)::Nothing
  ForwardDiff.jacobian!(J,func,dx,x, ForwardDiff.JacobianConfig(func,dx,x,ForwardDiff.Chunk{10}()))
  return nothing
end

# Variables
dx = zeros(1000)
x = ones(1000)
J = zeros(1000,1000)

# Actual function calls
@btime func(dx,x) # Zero allocations

@btime jac!(J,dx,x) # Four allocations

That’s because you are constructing the JacobianConfig object inside jac! function, thus re-allocating at each jac! call. This version does not allocate:

using ForwardDiff, BenchmarkTools

# Functions
function func(dx,x)::Nothing
  @. dx = 2*x
  return nothing
end

function jac!(J,dx,x,cfg)::Nothing
  ForwardDiff.jacobian!(J,func,dx,x,cfg)
  return nothing
end

# Variables
dx = zeros(1000)
x = ones(1000)
J = zeros(1000,1000)
# construct the JacobianConfig object in advance:
cfg = ForwardDiff.JacobianConfig(func,dx,x,ForwardDiff.Chunk{10}())

# Actual function calls
@btime func(dx,x) # Zero allocations

@btime jac!(J,dx,x,cfg) # Zero allocations now !!!