reduce_transposes: stop passing transposes through pow and softplus_parametric - #2784
Open
LeSingh1 wants to merge 1 commit into
Open
reduce_transposes: stop passing transposes through pow and softplus_parametric#2784LeSingh1 wants to merge 1 commit into
LeSingh1 wants to merge 1 commit into
Conversation
…arametric
_UNARY_LIKE_OP_TYPES documents itself as ops with a "single non constant
input" for which "Transpose(op(x)) == op(Transpose(x))". Two entries do not
satisfy that.
pow is an elementwise binary op (class pow(elementwise_binary)); its exponent
broadcasts against x. When the exponent is not a scalar, cancelling the
transposes around it re-binds the exponent to a different axis:
@mb.program(input_specs=[mb.TensorSpec(shape=(3, 3))])
def prog(x):
t = mb.transpose(x=x, perm=[1, 0])
p = mb.pow(x=t, y=np.array([1., 2., 3.], dtype=np.float32))
return mb.transpose(x=p, perm=[1, 0])
['transpose', 'pow', 'transpose'] -> ['pow']
For x = arange(1, 10).reshape(3, 3) the program used to return
[[1,2,3],[16,25,36],[343,512,729]] and now returns
[[1,4,27],[4,25,216],[7,64,729]]. With a non-square x the rewritten program
does not even build: "Incompatible dim 1 in shapes (3, 2) vs. (1, 3)".
softplus_parametric applies alpha[i]/beta[i] along axis 1 of its input, so a
transpose that moves axis 1 changes which channel each parameter applies to.
The torch frontend emits this op for nn.Softplus with a non-default beta.
Keep pow in the set but only treat it as unary-like when its exponent
broadcasts identically for every axis order (all dims 1), so the common
pow(x, 2.0) case still cancels its transposes. Drop softplus_parametric, which
is never safe here.
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.
Problem
_TransposeOptimization._UNARY_LIKE_OP_TYPESdocuments itself as ops with a "single non constant input" for which "Transpose(op(x)) == op(Transpose(x))". Two of its entries do not satisfy that, andcommon::reduce_transposesruns in the default pipeline.powis an elementwise binary op (class pow(elementwise_binary)iniOS15/elementwise_binary.py) — its exponent broadcasts againstx. Cancelling the transposes around it re-binds the exponent to a different axis:The original program computes
out[a][b] = x[a][b] ** y[a]; the rewritten one computesout[a][b] = x[a][b] ** y[b]. Withx = np.arange(1, 10).reshape(3, 3):[[1, 2, 3], [16, 25, 36], [343, 512, 729]][[1, 4, 27], [4, 25, 216], [7, 64, 729]]No warning, no error. With a non-square input the rewritten program does not even build — the same program with
xof shape(3, 2)raisesValueError: Incompatible dim 1 in shapes (3, 2) vs. (1, 3)from inside the pass.softplus_parametricappliesalpha[i]/beta[i]along axis 1 of its input (seeiOS15/activation.py, which requiresalpha.shape == (x.shape[1],)). A transpose that moves axis 1 therefore changes which channel each parameter applies to. The torch frontend emits this op fornn.Softpluswith a non-defaultbeta, so it is reachable from a normal conversion. Same repro shape:max|original - rewritten|here is75.0.Fix
powstays in the set but is only treated as unary-like when its exponent broadcasts identically for every ordering of the axes, i.e. all of its dims are 1 and its rank does not exceedx's. This keeps the optimization for the commonpow(x, 2.0)case while making the broadcasting case fall through to_visit_materialize_op, which is the conservative/correct handling.softplus_parametricis removed from the set; there is no input for which passing an axis-permuting transpose through it is safe.A possible follow-up (not done here, to keep this change small) would be to register
powas an axis-update op alongsideadd/mul/sub/… in_TransformAdd, which would recover the optimization for a broadcasting exponent by transposing the exponent as well.Tests
Three tests in
test_reduce_transposes_pass.py:test_no_fusion_pow_with_broadcasting_exponent— fails onmain(transposes are removed), passes with the fix.test_no_fusion_softplus_parametric— fails onmain, passes with the fix.test_fusion_pow_with_scalar_exponent— guards that the scalar case still fuses (passes both before and after).I ran the whole of
coremltools/converters/mil/mil/passes/tests/test_reduce_transposes_pass.pybefore and after; the set of failures is identical (my environment cannot load CoreML.framework, so theassert_model_is_validpredictions fail there either way — the graph-structure assertions that precede them all run and pass).