Faster way of calculate two-argument ForwardDiff gradient?

i have a function f(x1,x2) . sometimes i need dfdx1 , sometimes i need dfdx2, those cases are easy with the existing ForwardDiff API. the problem is when i need the two properties at once. gradient is one way, calling each time dfdx1 and dxdx2 is fine too, but is there a way to calculate two derivatives at once in one function evaluation? some example code to test

function f(x1,x2) 
res = x1+x2
  for i = 1:15
    res = sin(res)+x1 - cos(x2)
  end 
  return res
end

function df_grad(f,x1,x2)
  x = [x1,x2]
  _f = x-> f(xx[1],xx[2])
  g = ForwardDiff.gradient(_f,x)
  return g[1], g[2]
end

function df_twice(f,x1,x2)
  return ForwardDiff.derivative(x->f(x,x2),x1) , ForwardDiff.derivative(x->f(x1,x),x2)
end

Here’s one solution:

function grad2(f, x1::Number, x2::Number)
    y1 = ForwardDiff.Dual(x1, (true,false))
    y2 = ForwardDiff.Dual(x2, (false,true))
    f(y1, y2).partials.values
end

@btime df_twice(f, 1, 2)
@btime grad2(f, 1, 2)
3 Likes