EDI v1.0.1 Exhaustive C++ Model Fit Benchmarks

Generated: 2026-09-24 09:32:23 IDT

R analog of benchmark_model_fits_python.html — same three tables, same table shape, same three-color row coding.

This report compares the performance of EDI's Rcpp-optimized model fitting paths against low-level canonical R implementations (e.g., glm.fit, lm.fit, coxph.fit) where possible.

Compilation Context

These rows are read from build metadata compiled into the loaded EDI shared object via edi_build_info_cpp().

Compilation warning: EDI model-fit timings are sensitive to the compiler flags used to build the loaded EDI.so. If EDI is compiled without the proper optimized flags, or with flags that are known to degrade these kernels such as problematic LTO builds, the benchmark can show substantial performance regressions that reflect the binary build rather than the modeling algorithms.

Benchmark Dataset Specification

All benchmarks were performed on a synthetic clinical-trial-scale dataset generated for each response type. The data generation process ensures numerical stability and fair solver comparison by using the following parameters:

Methodology

Results

EDI faster, significant   NA timing comparison   no canonical R implementation

ClassResponseEDI Time (ms)Canonical PkgCanonical FuncCanonical Time (ms)SpeedupTiming PvalEDI IterationsCanonical Iterations
InferenceAllSimpleWilcoxcontinuous0.22statsHL median pairwise diff3.2014.45x6.89e-26***NANA
InferenceContinGLMM (pairs)continuous0.20Noneno canonical R implementationNANANA9NA
InferenceContinOLScontinuous0.02statslm.fit0.2111.54x2.04e-22***NANA
InferenceContinQuantileRegrcontinuous1.59quantregrq.fit1.560.98x0.65NANA
InferenceContinRobustRegrcontinuous0.18MASSrlm(MM)76.75416.52x5.92e-23***8NA
InferenceIncidBinomialIdentityRiskDiffincidence0.39statsglm.fit(ident)2.155.55x1.5e-15***54
InferenceIncidGCompRiskDiffincidence0.23statsglm.fit+gcomp(RD)2.7212.07x1.17e-15***NANA
InferenceIncidGCompRiskRatioincidence0.26statsglm.fit+gcomp(RR)2.7610.59x6.63e-20***NANA
InferenceIncidKKCondLogitGLMMOneLikincidence9.63Noneno canonical R implementationNANANA6NA
InferenceIncidLogBinomialincidence0.66statsglm.fit(log)2.613.93x1.63e-29***84
InferenceIncidLogRegrincidence0.18statsglm.fit2.2812.86x4.06e-22***54
InferenceIncidModifiedPoissonincidence0.16statsglm.fit(modified)3.3520.37x9.77e-19***55
InferenceIncidProbitRegrincidence0.56statsglm.fit(probit)3.245.74x1.36e-09***74
InferenceIncidRiskDiffincidence0.02statslm.fit(LPM)0.167.95x5.97e-15***NANA
InferenceCountGLMM (pairs)count7.73Noneno canonical R implementationNANANA21NA
InferenceCountHurdleNegBincount2.01psclhurdle(nb)63.6731.75x8.94e-19***21NA
InferenceCountHurdlePoissoncount6.29psclhurdle40.926.51x2.69e-20***64NA
InferenceCountHurdlePoisson (pairs)count4.16Noneno canonical R implementationNANANA20NA
InferenceCountKKCondPoissonOneLikcount0.08Noneno canonical R implementationNANANA5NA
InferenceCountNegBincount1.01MASSglm.nb27.0626.9x1.38e-12***241
InferenceCountPoissoncount0.21statsglm.fit3.3816.44x9.12e-23***65
InferenceCountQuasiPoissoncount0.26statsglm.fit(quasi)3.0611.66x9.09e-18***75
InferenceCountRobustPoissoncount0.21statsglm.fit2.7713.49x2.62e-21***65
InferenceCountZeroInflatedNegBincount18.12psclzeroinfl(nb)580.5032.04x5.88e-24***4228
InferenceCountZeroInflatedPoissoncount5.15psclzeroinfl356.0069.11x5.26e-21***79184
InferencePropBetaRegrproportion1.48betaregbetareg.fit46.3031.26x8.78e-27***714
InferencePropFractionalLogitproportion0.21statsglm.fit(quasi)2.2210.77x4.64e-20***54
InferencePropGCompMeanDiffproportion0.23statsglm.fit(quasi)+gcomp2.108.97x7.04e-21***NANA
InferencePropZeroOneInflatedBetaRegrproportion4.64Noneno canonical R implementationNANANA23NA
InferenceSurvivalCoxPHRegrsurvival0.60survivalcoxph.fit(breslow)1.171.94x5.98e-15***44
InferenceSurvivalGLMMWeibullFrailtyNormalOneLiksurvival1.84Noneno canonical R implementationNANANA6NA
InferenceSurvivalKMDiffsurvival0.02survivalsurvfit(median)5.61271.68x7.43e-27***NANA
InferenceSurvivalLogRanksurvival0.05survivalsurvdiff2.7954.52x9.55e-30***NANA
InferenceSurvivalRestrictedMeanDiffsurvival0.02survivalsurvfit(rmean)3.54177.19x1.48e-22***NANA
InferenceSurvivalStratCoxPHRegrsurvival1.03survivalcoxph.fit(strat)1.231.19x1.22e-05***43
InferenceSurvivalWeibullRegrsurvival0.25survivalsurvreg5.7723.29x5.09e-25***96
InferenceOrdinalAdjCatLogitRegrordinal1.25VGAMvglm(acat)22.5618.11x2.17e-23***105
InferenceOrdinalCLMM (pairs)ordinal28.93Noneno canonical R implementationNANANA23NA
InferenceOrdinalCauchitRegrordinal0.76ordinalclm(cauchit)12.7116.77x4.11e-16***107
InferenceOrdinalCloglogRegrordinal0.83ordinalclm(cloglog)11.4713.84x8.37e-26***85
InferenceOrdinalContRatioRegrordinal0.32VGAMvglm(cratio)23.7174.5x2.81e-33***95
InferenceOrdinalGCompMeanDiffordinal1.15ordinalclm+gcomp25.4022.07x9.02e-25***NANA
InferenceOrdinalGLMM (pairs)ordinal371.00Noneno canonical R implementationNANANA39NA
InferenceOrdinalOrderedProbitRegrordinal0.71ordinalclm(probit)11.5316.13x5.13e-18***74
InferenceOrdinalPropOddsRegrordinal0.99ordinalclm13.6313.77x2.59e-22***84

Wald Test Performance (Full Inference)

This table compares the performance of Full Inference (Model Fit + Standard Error calculation + P-value derivation). Unlike the point-estimation table above, these results include the computational cost of the variance-covariance matrix (Hessian or Fisher Information) and the Wald test statistic calculation. All paths (EDI and Canonical) use a reduced sample size ($N=200$) for this full-inference benchmark to ensure iterative stability. Stratified Cox Exception: For InferenceSurvivalStratCoxPHRegr, the benchmark injects low-cardinality covariates before outcome generation so the row exercises a genuinely stratified Cox fit rather than the unstratified fallback. EDI regression models (Logistic, Poisson) are benchmarked using the IRLS optimizer for these Wald tests. Solver-Only Prebuilds: Benchmark setup prebuilds exposed observed-data design matrices, reduced design matrices, strata IDs, and other fixed working inputs outside the timed region when the implementation exposes those hooks. The timed region then measures the full-inference kernel on those fixed inputs. Limitation: Some canonical comparators only expose formula-based APIs rather than comparable low-level fit kernels. Those rows remain included, but their canonical timings may still contain formula/model-frame overhead beyond the numerical solver, variance, and p-value work itself. Timing Note: All timings are medians over 30 warmed runs measured with adaptive batched system.time; paths below 0.01 ms use microbenchmark(times = 5000) instead. Timing P-Value: Timing Pval reports a Welch two-sample t-test comparing the EDI and canonical timing replicate distributions for each row. The unlabeled final column marks thresholds with *** for p < 0.001, ** for p < 0.01, and * for p < 0.05. Row Highlighting: Light green rows indicate Speedup > 1 and Timing Pval < 0.05; light grey rows indicate NA timing comparisons from a failed fit; light blue rows are estimators with no canonical R implementation at all (only EDI is timed, Canonical Time/Speedup/Timing Pval are NA by design).

EDI faster, significant   NA timing comparison   no canonical R implementation

ClassResponseEDI Time (ms)Canonical PkgCanonical FuncCanonical Time (ms)SpeedupTiming PvalEDI IterationsCanonical Iterations
InferenceAllSimpleMeanDiffPooledVarcontinuous0.07statst.test(pool)0.324.84x3.3e-12***NANA
InferenceAllSimpleWilcoxcontinuous0.10statswilcox.test1.0410.16x1.54e-14***NANA
InferenceContinGLMM (pairs)continuous0.23Noneno canonical R implementationNANANANANA
InferenceContinLincontinuous0.32statslm.fit(interact)+Wald1.073.38x9.98e-16***NANA
InferenceContinOLScontinuous0.02statslm.fit+Wald0.094.08x1.28e-18***NANA
InferenceContinQuantileRegrcontinuous2.79quantregrq+summary3.111.12x0.0519NANA
InferenceContinRobustRegrcontinuous0.08MASSrlm+summary2.1126.26x3.86e-23***10NA
InferenceIncidExactFisherincidence1.45statsfisher.test1.691.17x0.22NANA
InferenceIncidGCompRiskDiffincidence0.16statsglm+gcomp(RD)+Wald3.8223.77x3.21e-19***NANA
InferenceIncidGCompRiskRatioincidence0.12statsglm+gcomp(RR)+Wald4.0032.58x3.17e-15***NANA
InferenceIncidKKCondLogitGLMMOneLikincidence6.02Noneno canonical R implementationNANANANANA
InferenceIncidLogBinomialincidence0.86statsglm.fit+Wald(log)3.934.55x3.24e-27***33NA
InferenceIncidLogRegrincidence0.12statsglm.fit+Wald1.4311.82x1.45e-19***6NA
InferenceIncidMiettinenNurminenRiskDiffincidence0.02DescToolsBinomDiffCI(mn)1.1161.34x1.55e-20***NANA
InferenceIncidNewcombeRiskDiffincidence0.15DescToolsBinomDiffCI(score)1.227.89x4.91e-18***NANA
InferenceIncidProbitRegrincidence0.18statsglm.fit(probit)+Wald1.448.08x1.85e-25***9NA
InferenceIncidRiskDiffincidence0.02statsprop.test0.5323.55x9.09e-33***NANA
InferenceCountGLMM (pairs)count1.77Noneno canonical R implementationNANANANANA
InferenceCountHurdleNegBincount0.36psclhurdle(nb)+summary14.2539.5x1.09e-31***20NA
InferenceCountHurdlePoissoncount0.46psclhurdle+summary13.7629.96x6.07e-28***23NA
InferenceCountHurdlePoisson (pairs)count2.12Noneno canonical R implementationNANANANANA
InferenceCountKKCondPoissonOneLikcount0.08Noneno canonical R implementationNANANANANA
InferenceCountNegBincount0.22MASSglm.nb+summary17.8080.02x6.89e-27***12NA
InferenceCountPoissoncount0.11statsglm.fit+Wald1.3011.69x7.44e-19***7NA
InferenceCountQuasiPoissoncount0.09statsglm.fit+Wald(quasi)1.0611.54x6.18e-30***6NA
InferenceCountRobustPoissoncount0.14sandwichglm+vcovHC4.7933.37x2.4e-30***7NA
InferenceCountZeroInflatedNegBincount1.17psclzeroinfl(nb)+summary37.3331.91x9.88e-31***NANA
InferenceCountZeroInflatedPoissoncount0.45psclzeroinfl+summary26.3158.68x9.59e-21***33NA
InferencePropBetaRegrproportion0.33betaregbetareg+summary22.6269.41x1.18e-25***8NA
InferencePropGCompMeanDiffproportion0.11statsglm(quasi)+gcomp+Wald2.9628.13x2.13e-24***NANA
InferencePropZeroOneInflatedBetaRegrproportion1.35Noneno canonical R implementationNANANANANA
InferenceSurvivalCoxPHRegrsurvival0.22survivalcoxph.fit(breslow)+Wald0.602.67x7.41e-22***4NA
InferenceSurvivalGLMMWeibullFrailtyNormalOneLiksurvival1.49Noneno canonical R implementationNANANANANA
InferenceSurvivalGehanWilcoxsurvival0.03survivalsurvdiff(rho=1)2.4088.89x1.6e-28***NANA
InferenceSurvivalKMDiffsurvival4.01survivalsurvfit(median)+CI4.041.01x0.183NANA
InferenceSurvivalLogRanksurvival0.16survivalsurvdiff4.5128.59x3.06e-33***NANA
InferenceSurvivalStratCoxPHRegrsurvival0.58survivalcoxph.fit(strat)+Wald0.711.22x3.14e-11***4NA
InferenceSurvivalWeibullRegrsurvival0.17survivalsurvreg+summary4.3425.22x8.99e-25***10NA
InferenceOrdinalAdjCatLogitRegrordinal0.33VGAMvglm+summary20.0661.6x2.29e-32***9NA
InferenceOrdinalCLMM (pairs)ordinal14.25Noneno canonical R implementationNANANANANA
InferenceOrdinalContRatioRegrordinal0.10VGAMvglm+summary19.69188.91x1.13e-26***8NA
InferenceOrdinalGCompMeanDiffordinal0.50ordinalclm+gcomp+Wald8.4116.78x9.27e-33***NANA
InferenceOrdinalGLMM (pairs)ordinal65.67Noneno canonical R implementationNANANANANA
InferenceOrdinalJonckheereTerpstraTestordinal0.09clinfunjonckheere1.4716.43x3.29e-26***NANA
InferenceOrdinalPropOddsRegrordinal0.26ordinalclm+summary6.9526.71x7.11e-23***8NA
InferenceOrdinalRiditordinal0.06statsmean(ridit)0.406.67x6.22e-25***NANA

Garbage Collection and Cache Management

To ensure that the benchmark results are highly precise, reproducible, and represent the actual computation speed of the numerical solvers, the benchmarking harness uses the following garbage collection and cache management strategies:

1. Garbage Collection (GC) Filtering

Garbage collection cycles run automatically by the R interpreter and can introduce significant, arbitrary pauses that skew timing measurements. To isolate the execution time of the code from R's GC overhead:

2. Cold-Start Guarantee for EDI and Symmetric Warm-Up for Both Sides

Both EDI and canonical timing expressions receive a single validation/warm-up call executed once before the calibration loop begins. This puts the machine code and working data into the instruction and data caches in the same warmed state for both sides, so the official timed replicates start on equal footing.

EDI timings call exported C++ functions directly — no R6 objects are instantiated during benchmarking. As a result, no R6 result caches exist to manage. Each call to the C++ solver (e.g. fast_logistic_regression_cpp, fast_ordinal_regression_cpp) starts from a freshly zero-initialized parameter vector (or a model-specific data-driven initialization when smart_cold_start = TRUE). No prior-fit results are carried across timing repetitions, so every replication is a genuine cold start for the numerical optimizer.

Utility / Math Kernel Performance

This table is an exhaustive inventory of every fast_* scalar math kernel in EDI/src — used inside the NegBin/Beta/ZINB/Hurdle likelihoods, KK21 negative-binomial fitting, probit cold-start heuristics, ordinal cloglog/cauchit link derivatives, and LRT/score-test p-values — against base R's vectorized equivalents. Unlike the model-fit tables above, these are not full estimators: each row is a single vectorized special-function evaluation (digamma, trigamma, log-gamma, log-beta, error function, normal CDF/PDF/quantile (both closed-form and log-scale), chi-squared upper-tail p-value, arctangent, softplus, and the mu-parameterized negative-binomial density) over a fixed-length vector, with no design matrix, optimizer, or R6 object involved on either side. Vector length: All rows evaluate the function over a vector of length $N=5000$; inputs are drawn from a domain realistic for each kernel's actual call sites in EDI (e.g. shape/rate-like values in $(0.5, 50)$ for digamma/trigamma/lgamma, probabilities in $(0, 1)$ for qnorm). Bare Metal EDI Timing: Eight kernels (digamma, trigamma, lgamma, lbeta, dnbinom_mu, qnorm, log_pnorm, log_dnorm) call the package's own exported fast_*_vec_cpp wrapper (EDI/src/fast_math_utils.cpp, documented and exported via roxygen/NAMESPACE like any other EDI function) directly from the installed package — no separate compile step. The remaining six (pchisq_upper, erfc, pnorm_fast, dnorm_fast, atan, log1pexp) aren't promoted to package exports yet, so those rows call a thin bare-metal wrapper compiled standalone via Rcpp::sourceCpp() against the same EDI/src leaf headers (benchmark/fast_math_utils_bench.cpp) — same convention as benchmark/fast_trigamma_speed_compare.cpp. Either way, the wrapper just loops the internal fast_* scalar kernel over the input vector — no R6, no caching, no warm starts. Canonical R Timing: The base R column calls the corresponding vectorized base/stats function directly on the same input vector (e.g. digamma(), lgamma(), stats::qnorm(), stats::dnbinom(..., mu = , log = TRUE)). Timing Note: All timings use the same adaptive batched system.time/microbenchmark harness as the tables above (medians over 30 cold samples; paths below 0.01 ms fall back to microbenchmark(times = 5000)). Timing P-Value: Timing Pval reports a Welch two-sample t-test comparing the EDI and base R timing replicate distributions for each row. The unlabeled final column marks thresholds with *** for p < 0.001, ** for p < 0.01, and * for p < 0.05. Row Highlighting: Light green rows indicate Speedup > 1 and Timing Pval < 0.05; light grey rows indicate NA timing comparisons from a failed evaluation.

EDI faster, significant   NA timing comparison   no canonical R implementation

FunctionResponseEDI Time (ms)Canonical PkgCanonical FuncCanonical Time (ms)SpeedupTiming Pval
dnorm_fastutility0.07base/statsdnorm0.182.49x6.57e-25***
fast_atanutility0.07base/statsatan0.121.85x3.12e-11***
fast_digammautility0.13base/statsdigamma0.816.22x7.86e-10***
fast_dnbinom_muutility0.75base/statsdnbinom(mu=, log=TRUE)0.841.12x0.434
fast_erfcutility0.14base/stats2*pnorm(-x*sqrt(2))0.453.15x1.03e-13***
fast_lbetautility0.34base/statslbeta0.671.96x6.95e-18***
fast_lgammautility0.15base/statslgamma0.271.84x9.09e-22***
fast_log1pexputility0.10base/statslog1p(exp(x))0.151.48x3.08e-16***
fast_log_dnormutility0.03base/statsdnorm(log=TRUE)0.143.91x4.64e-20***
fast_log_pnormutility0.18base/statspnorm(log.p=TRUE)0.462.58x1.08e-17***
fast_pchisq_upperutility0.79base/statspchisq(lower.tail=FALSE)1.531.95x4.32e-15***
fast_qnormutility0.05base/statsqnorm0.152.98x4.58e-26***
fast_trigammautility0.06base/statstrigamma1.0518.4x1.8e-16***
pnorm_fastutility0.12base/statspnorm0.413.46x1.8e-17***