While optimizing Student pair-copula conditionals in VineCopulas.jl, I found that the native Student-t CDF and especially the quantile can be substantially slower than the corresponding Rmath routines.
Using:
- StatsFuns v2.2.1
- Rmath v0.9.0
a small benchmark gives:
using BenchmarkTools, StatsFuns, Rmath
ν = 5.0
x = 1.5
@btime StatsFuns.tdistcdf($ν, $x)
# 355.423 ns (0 allocations)
@btime Rmath.pt($x, $ν)
# 230.705 ns (0 allocations)
For the quantile:
p = 0.95
@btime StatsFuns.tdistinvcdf($ν, $p)
# 1.396 μs (0 allocations)
@btime Rmath.qt($p, $ν)
# 561.773 ns (0 allocations)
and in the tail:
p = 1e-8
@btime StatsFuns.tdistinvcdf($ν, $p)
# 1.962 μs (0 allocations)
@btime Rmath.qt($p, $ν)
# 302.579 ns (0 allocations)
The numerical results agree essentially to machine precision.
For these examples, Rmath is about 1.5× faster for the CDF, 2.5× faster for a central quantile, and 6.5× faster for the tail quantile.
This matters downstream in Copulas.jl and VineCopulas.jl, where Student conditional CDFs and quantiles are repeatedly evaluated during Rosenblatt transforms and simulation. A related discussion is tracked in lrnv/Copulas.jl#381.
Would there be room to optimize the native tdistcdf / tdistinvcdf implementations, particularly the inverse CDF, while keeping the native Julia implementation?
While optimizing Student pair-copula conditionals in
VineCopulas.jl, I found that the native Student-t CDF and especially the quantile can be substantially slower than the correspondingRmathroutines.Using:
a small benchmark gives:
For the quantile:
and in the tail:
The numerical results agree essentially to machine precision.
For these examples,
Rmathis about 1.5× faster for the CDF, 2.5× faster for a central quantile, and 6.5× faster for the tail quantile.This matters downstream in
Copulas.jlandVineCopulas.jl, where Student conditional CDFs and quantiles are repeatedly evaluated during Rosenblatt transforms and simulation. A related discussion is tracked inlrnv/Copulas.jl#381.Would there be room to optimize the native
tdistcdf/tdistinvcdfimplementations, particularly the inverse CDF, while keeping the native Julia implementation?