Repository navigation
Releases: seantalts/stanli
Release list
stanli 0.25.0
What's Changed
- Preserve Windows exception tables in embedded compiler builds by @seantalts in #503
- Make triangular-solve adjoint ownership explicit by @seantalts in #504
- Align macOS host dependencies and remove dependency warning patches by @seantalts in #505
- PR gate waits for the Windows compiler jobs; changelog written at release by @seantalts in #500
- Benchmarks page: one TL;DR, every number once by @seantalts in #506
- Memoize data-controlled loops during frame recording by @seantalts in #507
- Stop in-place writes from changing values a retained loop has already read by @seantalts in #508
- Fix the live CI flakes: timeouts, fetch retries, decode gate, baseline fetch by @seantalts in #510
- Make write_array and expression-effect checks linear in model size by @seantalts in #512
- Check the embedded stanc object at configure time and key it by its inputs by @seantalts in #511
- Lower deeply nested expressions on a large stack instead of crashing by @seantalts in #514
- Make generated-quantities loops and branches linear in prep time by @seantalts in #513
- Skip the deep-expression test under sanitizers by @seantalts in #515
- R: report compiled code from another install instead of a missing routine by @seantalts in #517
- Name every missing data variable in one error by @seantalts in #518
- Validate sampling and optimize arguments with clear messages by @seantalts in #519
- Show why proposals are rejected and print the same sampling warnings everywhere by @seantalts in #520
- Plain user-facing compile and data errors, with stanc3 warnings and the model file name by @seantalts in #521
- Lower csr_matrix_times_vector in linear time by @seantalts in #509
- Accept omitted zero-size data and send runtime output through R and Python stdout by @seantalts in #522
- Build repeated structured-loop frames from templates and lower write_array alongside log_prob by @seantalts in #524
- Fix main build: pass omitted data to the write_array lowering after log_prob by @seantalts in #525
- Fix int reads of 2-D int arrays written by rows (#523); container grid, OncoBayes2 corpus, compiled GQ by @seantalts in #527
- Trim the container write/read grid to 66 models by @seantalts in #528
- Fix Windows stack overflows and x87 precision on helper threads by @seantalts in #529
- Release 0.25.0 by @seantalts in #530
Full Changelog: v0.24.0...v0.25.0
stanli 0.24.0
Stanli 0.24.0 adds RStan-style sampling and variational inference, improves R and webR integration, and fixes Stan compatibility issues found in rbmi and OncoBayes2 models. The macOS arm64 packages also prepare large ctsem models faster.
R and webR
- Run RStan-style code on Stanli.
as_stanmodel()wraps Stan code, a.stanfile, or an RStanstanmodel. Pass it torstan::sampling()orrstan::vb()to use Stanli and receive astanli_stanfit. Sampling supports RStan's initialization forms, parameter selection, chain IDs, sampler controls, andalgorithm = "Fixed_param". Unsupported arguments produce explicit errors.rstan::optimizing()remains unsupported because its Jacobian convention differs; useoptimize_model()with its documented semantics. Packages with their own precompiled models, such as rstanarm, are outside this interface. (#499) - Choose chain IDs.
sample_model(chain_id = ...)assigns consecutive IDs and their random streams. With the same seed, four chains sampled together reproduce four separate one-chain runs with IDs 1 through 4. With Pathfinder initialization, all chains instead share one Pathfinder run seeded by the first chain's ID. (#497) - Pass higher-dimensional data.
stanli_model()accepts R arrays of any rank, including zero-length dimensions, and unnamed lists become arrays. Lists of matrices and vectors now map to their Stan array types. (#497) - Use simpler interoperability helpers.
parameter_names()lists declared parameters, withscalars = TRUEfor individual elements.unconstrain(ignore_unknown = TRUE)ignores extra entries in initialization lists.as_stanfit(plain = TRUE)returns an exactstanfitclass for clients that require it; it retains draws but drops the live model. (#497, #499) - Fit conversion and permuted extraction no longer change or depend on the caller's R random stream. Converted fits also tell brms that they hold a compiled model, avoiding unnecessary RStan recompilation for density evaluation. brms operations that refresh a fit still need a backend that samples with Stanli. (#497)
Stan compatibility and correctness
- Added
sort_asc,sort_desc,sort_indices_asc,sort_indices_desc, andrankfor integer and real arrays, vectors, and row vectors. Value sorting carries gradients and rejects NaN as Stan Math does. (#497) - Supported model sizes and slices computed by counter-based
whileloops, including forms used in rbmi's MMRM model. (#498) - Allowed data-size functions that call
print()orreject(), including OncoBayes2'sarray[M] vector[max_int(Nc)] w. They run once during data loading; random-number-generating size functions remain unsupported. (#498) - Fixed integer division promoted to real. Expressions such as
lower = -1 / (n - 1)now preserve Stan's integer division before conversion to a real value. Previously they could produce incorrect log densities. (#498)
Performance and evidence
- The macOS arm64 wheel and R runtime use a newer Apple Clang toolchain. On the measured 4,000-row, 580-parameter ctsem model, time to the first gradient fell from about 22 s to 13 s; warm gradients remained about 0.35 s. Three ordinary brms, rethinking, and cognitive models were unchanged or slightly faster in the measured phases. The deployment target remains macOS 11.0. (#501)
- The brms comparison now reports eight-seed reruns of the twelve models with one-sided convergence failures in the original run: 29 of 96 Stanli fits and 32 of 96 CmdStanR fits exceeded R-hat 1.01. No model consistently failed with one backend while converging with the other. Raw runs and the reproducible seed setting are included in the report. (#496)
Python, npm, and the R package/runtime are versioned together at 0.24.0. After upgrading the R package, run stanli::stanli_install() to fetch its matching runtime.
Known integration issues
- Windows x86_64 development builds with MSYS2 Clang have failures in three sort/rank rejection tests. The prebuilt Windows packages use GCC and pass those tests. (Development-build failure)
- The separately maintained
stanrpackage's pinned vendoring script has not caught up with the current runtime sources. Its compatibility job is nonblocking and fails withemit_message body not found, as it did in 0.23.2; this release does not claim downstreamstanrcompatibility. (Compatibility checks)
stanli 0.23.2
What's Changed
- TESTING.md: match what CI and the tools check today by @seantalts in #492
- Build CmdStan's SUNDIALS with -fPIC so BridgeStan can link it by @seantalts in #493
- Fix generated values that start a markdown line by @seantalts in #491
- Open the README with what Stanli is and its median speedups by @seantalts in #494
- Windows arm64 R binary: exact CSV fixture, release 0.23.2 by @seantalts in #495
Full Changelog: v0.23.1...v0.23.2
stanli 0.23.1
stanli 0.22.2
Faster inverse Gaussian cognitive models and refreshed benchmark tables.
Performance
- The inverse Gaussian cognitive model (
cm_invgaussian) gets gradients
about 1.9x faster. Loops with a very large body now run only the branch
each iteration takes, instead of every branch. - Large ctsem models get gradients about 1.03x faster.
Docs
- The benchmark tables are rerun for this release, so they include the
0.22.1 speedups for small ctsem models ands2_logistic_normal.
stanli 0.22.1
Fixes the 0.22.0 memory regression on large ctsem models and makes small
ctsem models faster.
Performance
- ctsem models with two observed variables get gradients about 2.8x faster,
ands2_logistic_normalabout 3.7x faster: 2x2 matrix products, solves,
Cholesky factors andmulti_normal_choleskyno longer allocate on the
heap. Larger ctsem models are unchanged. Results are bitwise identical.
Fixes
- Large ctsem models use far less memory again. 0.22.0 raised peak memory on
the 4,000-row ctsem model from issue #248 from 1.5 GB to 10.3 GB per chain.
Gradients on that model are back to their speed before 0.22.0, about 1.15x
slower than in 0.22.0. - A
returninside some user-defined functions no longer aborts the
process.
stanli 0.22.0
Faster brms and cognitive models through R and Python on Linux, faster
ctsem on large data, and a smaller C API.
Performance
- On Linux x86-64, the runtime library that R and Python load reaches Stan
Math's thread-local autodiff stack without a function call per access.
Models whose functions run Stan Math autodiff inside, such as
wiener_lpdf, get faster: on an i9-13900K the brms DDM-4 program from
issue #455 is 1.25-1.37x faster per gradient than in 0.21.0, and about 1.1x
faster than CmdStan. Results are bitwise identical. On other platforms the
reverse pass now looks up the autodiff stack once instead of once per
node. - ctsem models with large datasets: gradients are about 1.09x faster, and
peak memory is about 2x higher (0.74 GB to 1.6 GB at 64,000 rows).
Fixes
- Optimization now reports an error when generated quantities reject the
mode. It used to return success and leave that output row unwritten. - The batched sqrt gradient keeps the sign of a zero adjoint, matching the
scalar form bit for bit. - The web page runs every posteriordb model with 1000 warmup iterations and
1000 draws, the same as the built-in presets. It used 100 of each, too
short for many models to converge.
API changes
- The C API now has one entry point per operation, and its ABI version is 2.
Packages built against ABI version 1 (R packages before this release) refuse
the new runtime. The removed functions and their replacements:stanli_model_new,stanli_model_new_seededand
stanli_model_new_threaded: usestanli_model_new_with_opts.stanli_model_new_from_stan,stanli_model_new_from_stan_seededand
stanli_model_new_from_stan_threaded: use
stanli_model_new_from_stan_with_opts.stanli_stan_to_mirandstanli_stan_to_mir_with_includes: use
stanli_stan_to_mir_with_opts.stanli_sample,stanli_sample_streamandstanli_sample_stream_stats:
usestanli_sample_stream_stats_init.stanli_sample_multi,stanli_sample_multi_progress,
stanli_sample_multi_interruptibleandstanli_sample_multi_write_array:
usestanli_sample_multi_metric.
Docs
- The user docs are reorganized and shorter, one page per topic.
Pull requests
#468 user docs · #469 web page draw counts · #470 Linux TLS descriptors and grad() stack lookup · #471 simplification and C ABI 2 · #472 retained-loop engine · #473 release
Full changelog: v0.21.0...v0.22.0
stanli 0.21.0
Faster multilevel brms and cognitive models, multi-core brms threading(),
and CmdStan-style metric controls for sampling.
Performance
- Across the 343-model test corpus, gradients are 2.17x faster than
CmdStan in geometric mean, up from 1.95x in 0.20.0, and 1.10x faster than
0.20.0 on the models both releases measure. - brms random-effect loops are vectorized. Loops that update an element in
place (mu[n] += r[J[n]] * Z[n]) and loops that store to the same element
twice used to run one operation per observation. In the corpus,
ch13_m13_5goes from 3031 operations to 18 andch14_m14_2from 4053 to
36. On the multilevel models of issue #455 this also removes the slowdown
from running several chains at once and the growth of cost per observation
with N. Gradients of 45 corpus models move at rounding level. - brms
threading()programs use several cores whenthreads_per_chainis
above 1. Before, they ran on one core, and in 0.20.0 they were many times
slower than the plain program. On a 10,000-observation log-normal race model
a gradient is 2.8x faster at 4 threads and 3.5x faster at 8, and four chains
with 4 threads each sample in 10 s instead of 30 s. Data is shared between
threads and chains instead of copied. Areduce_sumis split only when each
chunk has about 30 microseconds of work, so small models stay on one thread
and are never slower. Threaded results depend onthreads_per_chain, which
sets the summation order, and can change between stanli versions; they do
not depend on thread scheduling.stanli_runprints a note when a model
with a largereduce_sumruns on one thread. - Cognitive race and diffusion models (the cogmod family):
cm_invgaussiansamples 4.0x faster with one chain and 4.6x faster with
four. Loops that uselog_sum_expover a range orinv_logitnow run 64
observations at a time. This uses more memory: peak memory with four
chains rises from 59 MB to 114 MB.cm_lnrandcm_rdmgradients are about 1.5x faster: the reverse pass
of loops with branches no longer zeroes its scratch buffer.wiener_lpdfevaluates the density once per gradient instead of twice,
also when its log density is weighted as in a mixture, and data
arguments are no longer differentiated. About 1.5x faster on a model
that is oney ~ wiener(...)statement. Gradients move by at most 7 ULP
on the DDM models tried.- In loops with many branches that run one observation at a time, the
reverse pass visits only the blocks that ran. The gradient is up to 9x
faster at points where most observations return early.
- Preparing a model allocates less in the function registry; median
preparation time is about 1.6% shorter.
Features
sample_model()andsample_cstan()in R, andModel.sample()in Python,
takemetric("diag_e","dense_e"or"unit_e"), a starting
inv_metric,step_sizeandadapt_engaged, as CmdStanR and CmdStanPy
do. The fit reports the step size and inverse metric each chain holds after
warmup (fit$step_size,fit$inv_metric, and$inv_metric()on
as_cstanfit()objects in R;fit.step_size,fit.inv_metricand
fit.metricin Python), so a pilot fit's metric can start the next one.
The C API gainsstanli_sample_multi_metricwith the same controls;
stanli_sample_optsand the ABI version are unchanged.
Fixes
- ctsem models were lowered as one operation per data row since 0.19.0, so
preparation time and memory grew with the data. The Kalman loop is one loop
again: at 2000 subjects, preparation goes from 18 s to under 1 s and peak
memory from 1.5 GB to 156 MB. A 400-subject ctsem model is now in the test
corpus. - The runtime builds inside stanr again. The execution report no longer
needs rapidjson's writer headers, which stanr's vendored Stan does not ship.
API changes
- C++ callers that set
CompileOptions::reduce_sum_min_elementsshould set
reduce_sum_min_chunk_nsinstead (default 30000, 0 to always split).
Testing
- Eight brms test fixtures (
s2_car,s2_car_esicar,s2_gr_by,s2_mm,
s2_mm_weights,s2_mmc,sw_re_bern,sw_skewnormal) are gated on
gradient error in ULP of the largest gradient entry (limit 10, measured at
most 2) instead of per element. Against a 60-digit reference,s2_mmand
s2_gr_byare slightly farther on one small entry (by 2e-16 and 6e-16);
the other six are closer.
Pull requests
#456 in-place loop vectorization (#455) · #457 wiener_lpdf partials · #458 sampler metric controls · #459 benchmark gate, stanr build fix · #461 region map lanes and branch trail · #462 preparation overhead · #463 lane memory · #464 multi-core threading() · #467 release
Full changelog: v0.20.0...v0.21.0
stanli 0.20.0
What's Changed
- Check the Linux x86-64 runtime stays on the baseline ISA by @seantalts in #431
- Run chains in parallel with inits; keep data early returns and shared mixture probabilities on the fast path by @seantalts in #432
- Fix flaky explicit-inits parallel sampling test by @seantalts in #433
- Require Windows wheel checks before merging source PRs by @seantalts in #435
- Require clean compiler builds, corpus performance checks, and post-merge CI follow-up by @seantalts in #436
- Fix runtime and test compiler warnings by @seantalts in #434
- Run duplicate operations' backward steps as in-place updates by @seantalts in #437
- Fuse four densities, read rvar vectors in place, and drop the dead Stan Math kernels from release builds by @seantalts in #439
- Fast-mode groundwork (research notes, ISA benchmark workflow) plus opt-in AVX2 matrix kernels, off by default by @seantalts in #441
- Fuse lognormal, beta and gamma by @seantalts in #442
- Publish the 2026-10-07 corpus benchmark by @seantalts in #445
- Add a per-model fast_math option by @seantalts in #446
- Check fused density arguments with one vectorized pass by @seantalts in #444
- Record the fast-mode density candidates and the sw_skewnormal page-boundary effect by @seantalts in #448
- Retry the signature replay seed rename on Windows by @seantalts in #447
- Collapse repeated observations in fast mode: rows, per-group statistics, and a quadratic form by @seantalts in #443
- Fix the no-stdio build and collapse preparation cost; fast-mode gate in CI; beta_binomial tests by @seantalts in #449
- Fast mode: browser option, register fill alignment, sampling and accuracy checks by @seantalts in #450
- Support a brms backend: R additions, partial inits, counting loops; brm() end to end against rstan by @seantalts in #452
- Stan's other inference algorithms: fixed_param, Laplace, single-path Pathfinder, ADVI by @seantalts in #453
- R: declare rstantools in Suggests by @seantalts in #454
- Release 0.20.0 by @seantalts in #451
Full Changelog: v0.19.1...v0.20.0
stanli 0.19.1
- Reduce math overhead in eligible independent loops with native operations
forerfc,log1p,log1m_exp, andinv_square. - Batch eligible scalar density and unary function calls across loop lanes,
preserving their scalar values, gradients, and exception messages. Keep
per-lane calls for functions whose vector implementations round differently.
The pinned stanr integration still fails while vendoring the runtime. The fix is in stanr PR #5, which remains open. The standalone stanli R package is covered separately by required integration checks.
Install with pip install --upgrade stanli, npm install @seantalts/stanli, or the R installation instructions.