I’m trying to implement log barrier function for my gradient descent code:
It have an easy derivative (sum of elementwise log → elementwise reciprocal)
Here is the script for testing:
using Zygote
using BenchmarkTools
function log_barrier(v,lower_bound,upper_bound)
return -1/100*sum(log.(-(v .-upper_bound))) + -1/100*sum(log.(v .- lower_bound))
end
function log_barrier_derivative(v, lower_bound, upper_bound)
return -1/100 .*(1 ./ (v.-upper_bound) + 1 ./ (v.-lower_bound))
end
v = [1,2,3,4,5,6,7,8]
upper_bound = 10
lower_bound = 0
#Warm up JIT
display(@benchmark gradient(log_barrier,v,lower_bound,upper_bound))
println(" ")
display(@benchmark log_barrier_derivative(v, lower_bound, upper_bound))
and the output:
byakuya@seireitei ~/asdfggg> julia asdf.jl
BenchmarkTools.Trial:
memory estimate: 5.08 KiB
allocs estimate: 156
--------------
minimum time: 11.210 μs (0.00% GC)
median time: 13.368 μs (0.00% GC)
mean time: 14.649 μs (1.88% GC)
maximum time: 2.794 ms (98.78% GC)
--------------
samples: 10000
evals/sample: 1
BenchmarkTools.Trial:
memory estimate: 576 bytes
allocs estimate: 4
--------------
minimum time: 158.838 ns (0.00% GC)
median time: 162.543 ns (0.00% GC)
mean time: 191.749 ns (7.44% GC)
maximum time: 2.385 μs (92.14% GC)
--------------
samples: 10000
evals/sample: 792
What happened? How can a handwritten derivative be like 70x faster than Zygote? Is it possible to make Zygote or other automatic differentiation faster so I don’t need to hand derive all of my functions?