Const fold scatter_along_axis and scaled_dot_product_attention correctly - #2802
Open
LeSingh1 wants to merge 1 commit into
Open
Const fold scatter_along_axis and scaled_dot_product_attention correctly#2802LeSingh1 wants to merge 1 commit into
LeSingh1 wants to merge 1 commit into
Conversation
Both ops had a value_inference that ignored an input which changes the result, so a program whose operands happen to be const folds to the wrong value and the op disappears from the model. scatter_along_axis: value_inference always called np.put_along_axis, i.e. it always computed mode="update". Every other mode was folded to the overwrite result, including the default mode="add". Compute the mode's reduction with the matching numpy ufunc applied through ufunc.at so that repeated indices accumulate, which is what the runtime does. scaled_dot_product_attention: value_inference only applied attn_mask when the mask had a value, and otherwise silently produced unmasked attention. This op has no @precondition, so with const query/key/value and a mask computed at runtime the whole attention collapsed to a const of the unmasked result. Return None instead, so the op stays in the graph.
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.
Two ops have a
value_inferencethat ignores an input which changes the result. When the operands happen to be const, the op is folded to the wrong value and then removed from the model byconst_elimination, so the model is silently wrong rather than failing to convert.scatter_along_axisignoredmodevalue_inferencealways callednp.put_along_axis, i.e. it always computedmode="update". Every other mode folded to the overwrite result — includingmode="add", which is the op's own default.modeupdate[[100, 2, 30]][[100, 2, 30]]add[[100, 2, 30]][[111, 2, 33]]sub[[100, 2, 30]][[-109, 2, -27]]mul[[100, 2, 30]][[1000, 2, 90]]div[[100, 2, 30]][[0.001, 2, 0.1]]max[[100, 2, 30]][[100, 2, 30]]min[[100, 2, 30]][[1, 2, 3]]The runtime column was measured by running the same program with
data/updatesas model inputs on this machine.The fix computes each mode with the matching numpy ufunc applied through
ufunc.at, so repeated indices accumulate the way the runtime does (addabove gives1 + 10 + 100). Negative indices keep wrapping, as before.divon an integer tensor is not folded, because numpy cannot write a float quotient back into an integer array.iOS17.scatter_along_axisinherits thisvalue_inference, so it is fixed too.scaled_dot_product_attentiondropped a non-constattn_maskWhen
attn_maskis present but computed at runtime,float_maskstayedNoneand the op folded to unmasked attention. This op has no@precondition, sovalue_inferenceruns whenever it is asked to, and with constquery/key/valuethe entire attention collapsed into a const of the wrong answer.The fix returns
Nonein that case, so the op stays in the graph and the mask is applied at runtime.Testing
New tests in
iOS14/test_scatter_gather.pyandiOS18/test_transformers.py. For each op there is a builder-eval test (the folded value) and arun_compare_buildertest (the runtime value), so the two are pinned to each other. In the attention backend test the attention output feeds amul, because a bad fold on a var that is directly a block output is not propagated byconst_eliminationand so would not be observable end to end.All 8 new tests fail on
mainand pass here. ExistingTestScatterAlongAxis(iOS14/16/17) andTestScaledDotProductAttentiontests still pass; they all usedmode="update"or a const mask, which are the two paths whose results are unchanged.