Hi all,
I have a the following example in Zygote for computing a single gradient, and I don’t understand why I get this performance regression over the following examples:
using SpecialFunctions,BenchmarkTools,Zygote,IrrationalConstants
function normcdf_wrong(x)
return erfc(x) / 2
end
function blsdelta_wrong(S0, K, r, T, σ, d)
rt = r * T
dt = -d * T
sigma_sqrtT = σ * sqrt(T)
S0_K = S0 / K
d_1 = (log(S0_K) + rt + dt) / sigma_sqrtT + sigma_sqrtT / 2
Δ = exp(dt) * normcdf_wrong(d_1)
return Δ
end
function normcdf_wrong_2(x)
return erfc(-x) / 2
end
function blsdelta_wrong_2(S0, K, r, T, σ, d)
rt = r * T
dt = -d * T
sigma_sqrtT = σ * sqrt(T)
S0_K = S0 / K
d_1 = (log(S0_K) + rt + dt) / sigma_sqrtT + sigma_sqrtT / 2
Δ = exp(dt) * normcdf_wrong_2(d_1)
return Δ
end
function normcdf_correct(x)
return erfc(-x * invsqrt2) / 2
end
function blsdelta_correct(S0, K, r, T, σ, d)
rt = r * T
dt = -d * T
sigma_sqrtT = σ * sqrt(T)
S0_K = S0 / K
d_1 = (log(S0_K) + rt + dt) / sigma_sqrtT + sigma_sqrtT / 2
Δ = exp(dt) * normcdf_correct(d_1)
return Δ
end
S0=100.0; K=100.0; r=0.02;T=1.2;σ=0.2; d=0.01;
@btime Zygote.gradient(blsdelta_wrong, $S0, $K, $r, $T, $σ, $d); #Performance are fine
@btime Zygote.gradient(blsdelta_wrong_2, $S0, $K, $r, $T, $σ, $d); #Allocating?
@btime Zygote.gradient(blsdelta_correct, $S0, $K, $r, $T, $σ, $d);#Allocating?
The first call is fine as performance, but unfortunately it isn’t correct. The second isn’t correct either but it is allocating (the only difference is a minus). The third one is correct from numerical point of view but it allocates for some reason.
Has anybody experienced anything like this?
(I think it is the first post I write, I am sorry in advance for the moderators)