Skip to content

Benchmarks ​

Benchmarks in VineCopulas.jl serve three different purposes:

  • the small Julia-only BenchmarkTools.SUITE in benchmark/benchmarks.jl tracks representative evaluation, fitting, selection, transforms and CDF workloads; Tachometer compares it on pull requests;

  • correctness gates show that the Julia implementation agrees with an external reference on deterministic fixtures;

  • performance benchmarks explain where the Julia implementation is fast, where it is near parity, and where optimization work remains.

Correctness before timing

A faster result is not meaningful until both implementations are known to be evaluating or fitting the same model. Read correctness reports before interpreting speed tables.

The continuous suite is intentionally distinct from the deeper R-backed campaigns below: the latter remain useful for parity and diagnosis, but are not required for ordinary pull-request benchmark comparisons.

Correctness against rvinecopulib ​

The external reference is R rvinecopulib, which wraps the C++ vinecopulib library. The correctness gate checks:

  • pair-copula log densities, h-functions, and inverse h-functions;

  • fixed general R-vine evaluation and transforms;

  • fixed-structure fitting;

  • automatic Dissmann-style structure selection.

Equivalent R-vine matrices can encode the same conditioned and conditioning sets, so the gate compares represented edges and numerical behavior rather than raw matrix text.

Run:

bash
PARITY_N=800 PARITY_FIT_MODE=common \
  bash benchmark/correctness/run_correctness_gate.sh

PARITY_N=800 PARITY_FIT_MODE=default \
  bash benchmark/correctness/run_correctness_gate.sh

The v0.1.1 release-candidate gate passed both supported parity modes:

ModeFitParametersStructureFamiliesFitted parameters
commonautomatic 10 / 10PASSPASSPASS
commonfixed 11 / 11PASSPASSPASS
defaultautomatic 11 / 11PASSPASSPASS
defaultfixed 11 / 11PASSPASSPASS

The fixed-model stage also passed all pair fixtures and both general R-vine fixtures. Representative fixed-vine discrepancies were around for log density and below   for inverse transforms.

Performance overview ​

The standard evaluation battery measures log density, Rosenblatt transform, inverse Rosenblatt transform, simulation, and numerical CDF behavior. It keeps evaluation separate from fitting because they stress different parts of the implementation.

Run:

bash
bash benchmark/run_main.sh

Fitting benchmarks use a separate entry point:

bash
bash benchmark/fitting/run_fit.sh

Tip

Use the benchmark reports to choose optimization targets. For example, standalone pair primitives and fused vine traversal can have different bottlenecks.

The reference evaluation campaign used   observations on an Apple Silicon macOS system with Julia 1.12.6, R 4.5.3, and rvinecopulib 0.7.3.1.0. These numbers are machine-specific, but the profile is useful:

FamilyJuliarvinecopulibInterpretation
Gaussian514.0 ms21.9 msJulia 1.56× faster
Gaussian1016.8 ms33.0 msJulia 1.96× faster
Gaussian2037.9 ms72.0 msJulia 1.90× faster
Clayton513.7 ms18.8 msJulia 1.38× faster
Clayton1017.1 ms27.6 msJulia 1.62× faster
Clayton2039.3 ms61.8 msJulia 1.57× faster
Gumbel531.0 ms30.1 msnear parity
Gumbel1038.4 ms45.3 msJulia 1.18× faster
Gumbel2085.3 ms100.1 msJulia 1.17× faster
Frank520.8 ms15.6 msR 1.33× faster
Frank1024.0 ms21.9 msR 1.10× faster
Frank2054.8 ms49.0 msR 1.12× faster

Gaussian and Clayton are consistently faster in this battery. Gumbel is close to parity, while Frank log density is modestly faster in rvinecopulib.

The fitting benchmark is currently the main performance gap:

TaskCommon model spaceDefault model space
Gaussian pair selectionR 3.40× fasterR 7.25× faster
Clayton pair selectionR 3.71× fasterR 8.45× faster
Fixed-structure R-vineR 3.16× fasterR 6.74× faster
Automatic R-vineR 3.31× fasterR 6.93× faster

This is not a correctness issue: the corresponding common and default correctness gates pass. It is the clearest performance target for future work.

Generic vs specialized pair conditionals ​

The architectural question is not simply whether hfunc1(C, u, v) is fast. It is whether the specialized vine spelling still adds value over the canonical Copulas.jl conditioning interface:

julia
hfunc1(C, u, v)
cdf(condition(C, 2, v), u)

hinv1(C, q, v)
quantile(condition(C, 2, v), q)

Focused diagnostics live in:

bash
julia --project=benchmark benchmark/diagnostics/condition_fallback.jl
julia --project=benchmark benchmark/diagnostics/fused_pair_kernels.jl
julia --project=benchmark benchmark/diagnostics/vine_engine_allocations.jl

The goal is to decide which optimized paths remain justified. Generic compatibility comes first; family-specific or fused methods should be retained when they are measurably faster, more stable, or avoid important allocations.

Reproducing results ​

Instantiate the benchmark environment:

bash
julia --project=benchmark -e '
using Pkg
Pkg.develop(path=".")
Pkg.resolve()
Pkg.instantiate()
'

Install the R reference dependency once:

bash
Rscript -e 'install.packages("rvinecopulib", repos="https://cloud.r-project.org")'

Then run the correctness and performance commands above from the repository root. Generated reports are written under benchmark/reports/ and benchmark/correctness/results/.

Note

Benchmark numbers are local measurements. They are useful for tracking regressions and prioritizing engineering work, not as hardware-independent guarantees.