complex _reshape_copy / _to_copy - #4516
Conversation
| node.replace_all_uses_with(out) | ||
| self.gm.graph.erase_node(node) | ||
| return True | ||
|
|
There was a problem hiding this comment.
this seems incorrect.
Two parts to this
-
_to_copy complex to real dtype cast produces silently wrong output
_rewrite_to_copy returns False for a real target dtype, apparently assuming this triggers the dispatcher's generic fallback (view_as_complex/view_as_real wrapping). It doesn't since the dispatcher only runs that fallback when no handler is registered for the op; since _to_copy.default is registered (via @_complex_unpacker), a registered handler returning False just leaves the node completely unmodified. -
z.to(torch.float32) should discard the imaginary part and return the original (unpacked) shape. But the lowered graph leaves the node untouched on the [..., 2] layout, so both components (and the extra trailing dim) survive. The test at present complex128 wont catch this since COMPLEX_TO_REAL_DTYPE[torch.complex128] = torch.float64, but the pre-existing to_copy_dtype_validator (aten_ops_converters.py) only allows {torch.float, torch.int32, torch.int64, torch.bool, torch.int8, torch.float16, torch.bfloat16} , float64 isn't in that set, so any _to_copy targeting it gets rejected by TRT and falls back to PyTorch anyway
0aae833 to
8922660
Compare
| dtype = kwargs.get("dtype") | ||
| inp = node.args[0] | ||
| to_real = dtype is not None and dtype not in COMPLEX_DTYPES | ||
| if dtype is not None and not to_real: |
There was a problem hiding this comment.
the rewrite assumes that any tensor being converted to a complex dtype is already stored in the internal [..., 2] real/imaginary layout. For a real tensor converted to complex, it does not create the required zero imaginary component before marking the result as complex. For example, [1, 2] should become [[1, 0], [2, 0]], but the rewrite leaves it as [1, 2]. so real to complex would fail
| with SubgraphBuilder(self.gm.graph, node) as b: | ||
| if to_real: | ||
| inp = b(torch.ops.aten.select.int, inp, -1, 0) | ||
| out = b(torch.ops.aten._to_copy.default, inp) |
There was a problem hiding this comment.
This always selects only the real component before casting. For boolean conversion eg: 0+1j, it selects 0, which becomes False while PyTorch returns True because the imaginary component is nonzero.
Description
The complex rewriter has no rules for aten._reshape_copy and aten._to_copy, so it inserts view_as_complex / view_as_real wrappers and forces an avoidable graph break. Dry-run then looks like the model uses unsupported complex views.
Register _reshape_copy with the existing reshape path and add a small _to_copy rewrite so those ops stay in the real-valued complex layout.
Fixes # (issue)
Type of change
Please delete options that are not relevant and/or add your own.
Checklist: