Repository navigation
Fix off_x/off_y typo in steel BaseMMAFrag::load_safe - #3565
Merged
Merged
Conversation
load_safe computes the source address with off_x in both terms: src[(off_x + i) * str_x + (off_x + j) * str_y]. The column term should use off_y. The bounds check immediately above uses (off_y + j) < lim_y, and the sibling store_safe and store_slice both compute (off_y + j) in their address arithmetic, so this is an isolated typo. Co-Authored-By: Claude Opus 4.7 <[email protected]>
1 task done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
BaseMMAFrag::load_safeinsteel/gemm/mma.husesoff_xwhereoff_ybelongs in its source-address computation.On current
main:The second term should be
(off_y + j). This is a typo, not intentional:(off_y + j) < lim_y.store_safeandstore_sliceboth compute the address as(off_x + i) * str_x + (off_y + j) * str_y— correct.loadusessrc[i * str_x + j * str_y]— correct.load_safeis the only one of the four that usesoff_xtwice — and it contradicts its own bounds check, which checks columnjagainstoff_y.Effect
MMATile::load_safecallsMMAFrag::load_safewithoff_x = (i * kFragRows) * w_xandoff_y = (j * kFragCols) * w_y, which differ for any fragment off thei == jdiagonal. The buggy term then folds the row-fragment offset into the column address, so fragments load from the wrong column band — a silent data corruption (no out-of-bounds access).Concretely, a
MMATile<float, 1, 32>loaded viaload_safereturns the first column-fragment's two columns replicated across all 32 column-fragments.I haven't audited MLX's own kernels for exposure —
Atile.load_safecall sites (e.g. inquantized.h) route through the deviceMMATile::load_safe, so flagging for maintainers to check.Fix
(off_x + j)→(off_y + j).Credit
The bug was discovered by Claude Opus 4.7 (Anthropic) while building a FlashAttention QK^T GEMM on
steel/gemm/mma.hin a downstream project, and traced to this line by static comparison against the three sibling loaders. This PR is opened from a human collaborator's GitHub account as Claude does not have its own.