Precompiling a function for `ForwardDiff` call

I am using ForwardDiff on my own function. While I expect that the first call spends a substantial amount of time compiling, subsequent identical calls are also spending 99.8+% of the time compiling. I have tried reviewing the precompiling tutorial, but I am lost.

julia> @time ForwardDiff.derivative(x -> myfn(arg1, arg2, arg3, x), 1.0)
  4.547712 seconds (6.87 M allocations: 457.011 MiB, 9.40% gc time, 99.89% compilation time)
julia> @time ForwardDiff.derivative(x -> myfn(arg1, arg2, arg3, x), 1.0)
  2.553844 seconds (4.39 M allocations: 290.645 MiB, 2.95% gc time, 99.84% compilation time)
julia> @time ForwardDiff.derivative(x -> myfn(arg1, arg2, arg3, x), 1.0)
  2.692889 seconds (4.39 M allocations: 290.668 MiB, 7.38% gc time, 99.85% compilation time)
julia> @time ForwardDiff.derivative(x -> myfn(arg1, arg2, arg3, x), 1.0)
  2.601984 seconds (4.39 M allocations: 290.660 MiB, 3.31% gc time, 99.85% compilation time)

If I know that all the arguments (including x) will be Float64 or Vector{Float64}, can I precompile this? Currently, I have declared my function in the where T style; would it help if that was different?

Clearly a possible 4 msec runtime is a lot more attractive than 2.5+ seconds for a function I expect to call hundreds of millions of times.

Welcome! You’re defining a new anonymous function x -> myfn(arg1, arg2, arg3, x) on every line, which must be compiled, and also requires the compilation of a corresponding method of ForwardDiff.derivative. To avoid this, wrap a function around the expression you’re benchmarking:

julia> f(y) = ForwardDiff.derivative(x -> myfn(arg1, arg2, arg3, x), y);

julia> @time f(1.0)

Also, arg1, arg2 and arg3 seem to be global variables, so for performance, make sure they are declared const.

2 Likes