Skip to content

BUG: matmul on Apple Silicon (Accelerate) writes out of bounds — silent data corruption, not just spurious FPE warnings #32464

Description

@MikeBarden

Related to #28790 and #29820, which report spurious FPE warnings from matmul on Apple Silicon as "annoying but harmless". On our workload the same code path silently corrupts an unrelated live array. Filing separately because the impact class is different.

Environment

  • macOS 26.6.2 (build 25G83), Apple M5 Pro, arm64
  • Python 3.14.4 (Homebrew), numpy 2.2.0, numpy.show_config()blas name: accelerate
  • scipy 1.17.1 (held constant throughout)

1. The known symptom reproduces in three lines

import numpy as np, warnings
with warnings.catch_warnings(record=True) as w:
    warnings.simplefilter("always")
    np.identity(15) @ np.identity(15)
    print([str(x.message) for x in w])
# ['divide by zero encountered in matmul', 'overflow encountered in matmul',
#  'invalid value encountered in matmul']   — result is correct

2. The corruption

In a scientific pipeline we have a float64 array of shape (255985,) — an owning copy, never assigned to anywhere in our source. Across a loop that calls scipy.spatial.ConvexHull and then all_pts @ hull_eqs[:, :3].T + hull_eqs[:, 3], that array's contents change between iterations. At the affected sites all inputs and outputs of the matmul are finite (|hull_eqs| <= 28.4, |signed| <= 55.8), so the reported overflow is impossible arithmetically and indicates access beyond the buffer.

Downstream this changed a boolean selection mask, hence a point set, hence a convex hull, hence an aggregate — moving a reported financial figure by +24% (33,977,903 -> 42,130,944) with no error and no warning other than the FPE noise above.

3. It behaves as heap-layout dependence

Adding a statement that merely holds references to the arrays — _keepalive = (a_f, c_f, d_f, v_f), computing nothing — makes the corruption vanish and restores the correct result. So does reversing an unrelated loop. Any instrumentation that closes over the array suppresses it, which made it self-defeating to measure.

4. Version isolation

Holding scipy at 1.17.1 and moving numpy alone:

numpy identity-matmul warnings our result
2.2.0 3 warnings corrupt
2.3.3 none correct
2.3.4 none correct

Under 2.3.4 the result is byte-identical across clean / keepalive / reversed-loop builds. We have pinned numpy>=2.3.4.

Question: was the out-of-bounds write fixed deliberately between 2.2.0 and 2.3.3, or incidentally? If the underlying Accelerate integration issue persists in any form, the harmless-warnings framing in #28790/#29820 understates the risk — this silently changed a number that people make decisions on.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions