[Fix][Relax][Frontend][Torch] Support aten.diagonal from decomposed repeated-subscript einsum - #20237
Open
siyiweigeHEW wants to merge 3 commits into
Open
[Fix][Relax][Frontend][Torch] Support aten.diagonal from decomposed repeated-subscript einsum#20237siyiweigeHEW wants to merge 3 commits into
aten.diagonal from decomposed repeated-subscript einsum#20237siyiweigeHEW wants to merge 3 commits into
Conversation
…ed-subscript einsum
from_exported_program runs run_decompositions() by default, which lowers
torch.einsum with repeated subscripts (diagonal / trace, e.g. "ii->i",
"ii->", "...ii->...i") to aten.diagonal + permute (+ sum). The torch
frontend had no handler for aten.diagonal.default, so every such valid
model failed with `AssertionError: Unsupported function types
['diagonal.default']`. The same root cause blocked torch.diagonal /
torch.trace.
Add BaseFXGraphImporter._diagonal lowering diagonal(x, offset, dim1, dim2)
as permute_dims (move dim1/dim2 to trailing axes) -> two strided_slice
(crop each trailing axis to the diagonal length, offset-adjusted) ->
relax.op.einsum("...zz->...z"). Handles static and dynamic (symbolic)
shapes, positive/negative offsets, and arbitrary dim1/dim2 (incl. negative
indices). Register "diagonal.default" in the exported-program convert_map
and "diagonal" in the from_fx convert_map.
Fixes: apache#20228
Removed unused import statement for torch.
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.
Fixes: #20228
Summary
from_exported_programrunsexported_program.run_decompositions()bydefault, and PyTorch's decomposition lowers
torch.einsumwith repeatedsubscripts (diagonal / trace, e.g.
"ii->i","ii->","...ii->...i") toaten.diagonal+permute(+sumfor the trace).aten.diagonal.defaultwas missing from the torch frontend
convert_map, so every such validmodel failed with:
This PR adds an
aten.diagonalconverter and registers it in both theexported-program and
from_fxconvert maps, so repeated-subscript einsum —and the directly-affected ops
torch.diagonal/torch.trace— convert andrun. Verified failing equations from the issue all convert with
max|diff| = 0vs PyTorch.
Root cause
BaseFXGraphImporter._check_unsupported_func_typeasserts when acall_functionnode's target is not inconvert_map. For the einsum familyabove,
run_decompositionsintroducesaten.diagonal.defaultnodes that thetorch frontend had no handler for, so conversion aborts at the assertion. This
is the same root cause for the direct ops
torch.diagonal(lowered todiagonal.defaultas-is) andtorch.trace(lowered todiagonal+clone+sum). Skipping decomposition (run_ep_decomposition=False) keeps the einsumnode intact and works — confirming the defect is the missing
diagonalhandling, not
relax.op.einsumsemantics.Fix
Add
BaseFXGraphImporter._diagonalinbase_fx_graph_translator.py, loweringdiagonal(input, offset=0, dim1=0, dim2=1)as:relax.op.permute_dims— movedim1/dim2to the trailing two axes;relax.op.strided_slice— crop each trailing axis to the diagonallength
min(extent1, extent2 ± offset)(offset-adjusted), so the twotrailing extents are equal;
relax.op.einsum([x], "...zz->...z")— the repeatedzlabel runs overboth trailing axes simultaneously, extracting the diagonal.
The lowering handles static and dynamic (symbolic) shapes, positive/negative
offsets, and arbitrary
dim1/dim2(including negative indices). Register"diagonal.default"inExportedProgramImporter.create_convert_mapand"diagonal"inTorchFXImporter.create_convert_map.Validation
In-tree regression test (added)
test_einsum_repeated_subscriptintests/python/relax/test_frontend_from_exported_program.py:verify_modelagainst the exact lowering IR for"ii->i"on the defaultdecomposition path (this case used to raise the assertion);
verify_model_numericallyfor"ii->"(trace),"...ii->...i"(batcheddiagonal), the attention-style two-operand
"abca,abcb->c", and the directops
torch.diagonal(x, offset, 0, 1)andtorch.trace.Differential test
verify_patch.pyruns on the locked build and simulates the pre-fix behaviorat runtime (popping
diagonal.defaultfrom the generated convert map):equations + 11 direct
torch.diagonal/torch.trace/torch.diag) reproducethe exact
AssertionError: Unsupported function types ['diagonal.default'];1 case (
torch.diagon a 1-D input, which goes throughdiag_embed) isunaffected and stays correct in baseline.
max|diff| = 0."ii->i"and"...ii->...i"with symbolic dims (bothdiagonal dims sharing one
Dim) match PyTorch exactly.batch matmul, ellipsis broadcasting/summation, 3-operand, implicit output) —
15 cases — all still match with
max|diff| = 0.Run:
Files changed
python/tvm/relax/frontend/torch/base_fx_graph_translator.py— add_diagonal(permute_dims + strided_slice crop + einsum...zz->...z).python/tvm/relax/frontend/torch/exported_program_translator.py— register"diagonal.default"in the exported-programconvert_map.python/tvm/relax/frontend/torch/fx_translator.py— register"diagonal"inthe
from_fxconvert_map.tests/python/relax/test_frontend_from_exported_program.py— addtest_einsum_repeated_subscriptregression coverage.