Add sym_float and trunc support for dynamic float-scale interpolate - #2843
SakshamKapoor2911 wants to merge 2 commits into
Conversation
| """ | ||
| try: | ||
| return export_fn() | ||
| except Exception as e: # noqa: BLE001 |
There was a problem hiding this comment.
You don't need the noqa comment.
| self, compute_unit, backend, frontend | ||
| ): | ||
| if frontend == TorchFrontend.EXECUTORCH: | ||
| pytest.xfail("executorch incorrectly propagates dynamic shape") |
There was a problem hiding this comment.
How is it incorrect? Is there a PyTorch issue for this?
| msg = str(e) | ||
| if "trunc" in msg or "SpecViolationError" in msg: | ||
| pytest.xfail( | ||
| "torch.export verifier rejects the trunc node on this torch version" |
There was a problem hiding this comment.
Why does it reject some of these models?
| assert len(layer.upsample.fractionalScalingFactor) == 0 | ||
|
|
||
| @staticmethod | ||
| def _xfail_if_torch_export_rejects_trunc(export_fn): |
There was a problem hiding this comment.
I think it would be much cleaner to only test valid use cases and not use this helper method.
Remove the _xfail_if_torch_export_rejects_trunc helper: current torch export verifier accepts the sym_float/mul/trunc decomposition, so the defensive xfail path is dead code. Call run_compare_torch directly. Drop ExecuTorch from the parametrization: dynamic-shape interpolate with symbolic output sizes is not supported by the ExecuTorch edge lowering (upper-bound/padded dynamic shapes only), so these tests now only exercise the TorchExport frontend, which is the valid use case.
|
@TobyRoseman Thanks for the review. I've refactored the two dynamic float-scale tests in Removed the Dropped the ExecuTorch frontend from these two tests (they now parametrize only Local verification: |
Summary
sym_floatandtruncPyTorch frontend lowerings so thatnn.functional.interpolate(..., scale_factor=<float>, recompute_scale_factor=True)converts over dynamic (symbolic) input shapes.torch.exportdecomposes the output-size computation intosym_float -> mul -> truncFX nodes, which previously failed withNotImplementedError: Unsupported fx node sym_float.sym_floatlowers a symbolic integer dimension (fromaten.sym_size) tofp32; since it is a runtime dimension, it stays dynamic.trunclowers tosign(x) * floor(|x|)(the same building blocks as the existingfraclowering) and is the identity on integer tensors; this also enablestorch.truncin the converter generally.int32inupsample_nearest1d/upsample_nearest2d, mirroring whatupsample_bilinear2dalready does, so the Torch upsample dialect ops receiveint32output sizes.torch_upsample_to_core_upsampleSSA pass to recover the constant floatscale_factorfrom the newcast(int32) -> trunc -> floor -> abs -> mulchain, and only fill in scale factors that earlier patterns could not resolve, so a previously resolved value (e.g. the constant dummy width of a 1d upsample) is not overwritten.Related to #2837 (symbolic
F.interpolate). This PR handles the floatscale_factordecomposition; the 1D symbolic-output-size rank fix is covered by #2840.Testing
Local (Linux) conversion/structure tests, plus numerically-executed MIL parity:
python -m pytest coremltools/converters/mil/frontend/torch/test/test_torch_ops.py -k "interpolate" -qResult:
4 passed, 4 xfailed(XFAILs are the pre-existing Executorch dynamic-shape limitation). FullTestUpsample:296 passed, 26 xfailed— no regressions.Numerical parity against PyTorch (fp32, converted MIL executed op-by-op): max diff
0.0for floatscale_factor2.0and(2.5, 1.5)over symbolic H/W, plus static-shape regressions.