Skip to content

0.14.2 — predict 1.35–1.63× faster, bit-identical

Choose a tag to compare

@bbstats bbstats released this 14 Jul 00:46
0d0fa1d

Cuts the 0.14.2 release. The diff here is just the version bump and CHANGELOG
date stamp -the changes being released are already on main (merge a5810fa).

What's in this release

Predict is 1.35–1.63× faster end-to-end, with predictions unchanged to the
last bit. Two changes:

  1. Row-major fused predict kernels (_predict_forest_rm,
    _predict_forest_linear_rm) — predict consumes the binner's row-major
    output directly, so each sample's bins sit in one or two cache lines for
    the whole forest walk and the per-predict feature-major transpose copy is
    gone. Fit-side kernels keep the feature-major layout (histograms want it);
    SHAP keeps the feature-major kernels for its background walk.
  2. No more whole-matrix copy for all-numeric input
    FeaturePreprocessor extracted the numeric block as
    X[:, num_features_] even when every column is numeric, a full
    fancy-index copy on each transform (~18% of end-to-end predict on large
    batches). Plain asarray now covers that case; mixed/categorical inputs
    keep the gather.

Numbers (fit 200k / predict 2M×30 / 200 trees / 12 threads, min-of-5)

config 0.14.1 0.14.2 speedup
classifier, linear leaves (default) 2.140 s 1.588 s 1.35×
classifier, constant leaves 1.244 s 0.764 s 1.63×
regressor 1.236 s 0.757 s 1.63×

Against the field on the same benchmark (benchmarks/scaling_predict.py):
default binary predict is now 1.26 Mrows/s — 1.30× LightGBM, 3.0×
sklearn-HGB, 0.50× XGBoost; constant-leaf paths reach ~2.6 Mrows/s, on par
with XGBoost. CatBoost's SIMD-fused C++ inference remains ~10× faster.

Why "bit-identical" is safe to claim

  • Exact-equality kernel test (test_rowmajor_predict_kernels_match_feature_major_exactly):
    row-major vs feature-major kernels compared with np.array_equal across
    depth-0 trees, constant and linear leaf blocks, NaN center bins, n ∈ {0, 1, many}.
  • Regenerated golden baseline changed only machine-relative timing ratios —
    every accuracy metric field is byte-identical.
  • Full suite: 378 passed. warmup() compiles the new kernels automatically
    (same numba argument types), so the 0.14.1 fresh-worker JIT fix carries over.

After merging

  • git tag v0.14.2 && git push origin v0.14.2
  • build + upload to PyPI

🤖 Generated with Claude Code