Skip to content

Fix several regressions caused by last release#2272

Open
ricardoV94 wants to merge 8 commits into
pymc-devs:mainfrom
ricardoV94:bugfixes
Open

Fix several regressions caused by last release#2272
ricardoV94 wants to merge 8 commits into
pymc-devs:mainfrom
ricardoV94:bugfixes

Conversation

@ricardoV94

@ricardoV94 ricardoV94 commented Jul 3, 2026

Copy link
Copy Markdown
Member

Also fixes a couple others that had been sitting on dev branches

  • Fix NaN propagation in Numba CAReduce max/min reductions
  • Fix unsound x[idx].set -> x[idx].inc rewrites with non-uinque indices
  • Don't fuse indexed reads/writes through a non-empty basic slice
  • Strip Elemwise inplace from fused indexed-write outputs
  • Soundly recognize reshaped takes when undoing transform_take
  • Fix Numba CAReduce of bitwise AND over unsigned integers
  • InnerGraph Ops: do not fallback to config mode linkers in python/cvm paths
  • Don't bail numba core-shape rewrite on RVs that already feed the node

The accumulation `if acc < arr: acc = arr` never takes a NaN, so max/min
silently dropped NaNs, diverging from numpy, the C backend (whose scalar
Maximum c_code explicitly tests both orderings to detect NaN), and the Python
perform. Append an `arr != arr` clause: NaN is taken once and then sticks.

The branch formulation compiles to a 2-compare/2-blend dependency chain,
about 2x faster than the 3-compare/3-blend chain numba generates for
np.maximum (which re-checks isnan(acc) every iteration).
@ricardoV94 ricardoV94 requested a review from jessegrabowski July 3, 2026 19:09
@ricardoV94 ricardoV94 added the bug Something isn't working label Jul 3, 2026
The fused loop writes the elementwise result to the write buffer, never to
the inplaced input, but the inner fgraph kept the inplace Elemwise: the
Python-mode fallback (OpFromGraph.perform) would destroy that input without
the outer destroy map declaring it, losing the ordering constraint for other
readers of the destroyed buffer. The JIT path was unaffected (write buffers
shadow the inplace pattern in make_outputs).

Write-and-direct duplication now runs before the strip and preserves the
inplace pattern, so an inplace on an output that stays materialized (the
write consuming a duplicate) still survives the fusion.
undo_take_reshape_for_fusion assumed the reshape restores the flattened
index's original shape without verifying it, so a gather regrouped to a
different (runtime) shape was silently rewritten to x[mat_idx], changing
the result shape and grouping.

Verify instead that the leading and trailing target dims provably pass
through the source, and build the ND index from the reshape target itself:
x[idx].reshape(S) -> x[idx.reshape(S[axis:...])]. This is also more general
than the flatten-form match: it fuses regroupings and reshapes of plain
vector-index takes, and no longer requires the index to come from a ravel.
The reduction identity for bitwise AND is -1 (all bits set). Coercing it to
an unsigned acc_dtype via the numpy scalar constructor (np.uint64(-1)) raises
OverflowError on NumPy 2, so any AND-reduction over an unsigned dtype failed
to compile. Cast through astype instead, which wraps -1 to all-ones the way
the C backend already does. OR/XOR (identity 0) were unaffected.
introduce_explicit_core_shape_rv refused to wrap a RandomVariable when its
core shape read the shape of another RandomVariable already feeding it (e.g.
an MvNormal whose random `mean`'s trailing dimension is the core shape). That
RV is computed before the node, so reading its shape needs no extra draw --
but `applys_between(node.inputs, [core_shape])` still yields such an input RV
as the owner of a boundary variable, so the node was left unwrapped and later
crashed numba funcify with "necessary to replace RandomVariable with
RandomVariableWithCoreShape".

Block the ancestor walk at the node's own inputs and only bail on a
RandomVariable reachable past them (a genuine extra draw for the shape).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant