Skip to content

Keep cat_out's nnlib input arrays off variable-length stack arrays (#24319) - #24319

Open
zonglinpeng wants to merge 2 commits into
pytorch:mainfrom
zonglinpeng:export-D128236590
Open

zonglinpeng wants to merge 2 commits into
pytorch:mainfrom
zonglinpeng:export-D128236590

Conversation

@zonglinpeng

@zonglinpeng zonglinpeng commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

impl::G3::native::cat_out declared variable-length arrays sized by the number of inputs (about 76 B per input) before it checked whether the xa_nn_cat path applies. A 256-input int64 cat in RT-DETR (rtdetr_r18vd, int8) therefore grew the frame by about 19 KB on the DSP thread that runs the operator, overflowed that thread's 7488 B stack and tripped the Zephyr stack sentinel on the first inference. Raising the stack did not help: 8 KB, 11.5 KB and 16 KB stacks all overflowed.

The nnlib path now runs only for same-dtype, supported-dtype cats with at most 16 inputs, and uses fixed-size arrays. Larger cats take the existing generic loop. The frame is a fixed 1440 B: the number of dynamic stack adjustments in cat_out goes from 11 to 0 in the built DSP image.

Adds a 40-input cat test case so the fallback branch is covered.

The 256 inputs are one tensor repeated: every entry of that cat references the same value and buffer. RT-DETR's decoder gathers with topk_ind.unsqueeze(-1).repeat(1, 1, d_model), and Cadence's ReplaceRepeatWithCatPass lowers a repeat as a cat of the same tensor, so d_model = 256 becomes a 256-entry cat. The kernel is still the place to fix the overflow: the arrays are sized by entry count, not by distinct tensors, and a 100-entry cat of distinct inputs (EfficientDet-Lite0's full graph) would need about 7.6 KB of them, more than the whole 7488 B stack. Lowering repeat as a broadcast copy would remove RT-DETR's long list but leave genuinely wide cats exposed, so it is at most a later optimization.

Differential Revision: D128236590

@pytorch-bot

pytorch-bot Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/24319

Note: Links to docs will display an error until the docs builds have been completed.

❌ 2 New Failures, 2 Pending

As of commit bec367b with merge base 822cb60 (image):

NEW FAILURES - The following jobs have failed:

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 30, 2026
@meta-codesync

meta-codesync Bot commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

@zonglinpeng has exported this pull request. If you are a Meta employee, you can view the originating Diff in D128236590.

@github-actions

Copy link
Copy Markdown

This PR needs a release notes: label

If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "release notes: none"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.

Summary:
`rlx_arbitrary_image_stylization` fails in the ExecuTorch emitter: `InternalError: Tensor has a memory_format that is unsupported in ExecuTorch: torch.channels_last` (`exir/tensor.py` `memory_format_enum` raises `KeyError: torch.channels_last`). Its export carries `clone(memory_format=torch.channels_last)` on ops that stay on the CPU.

Cadence lowers with `_skip_dim_order=True`, and so does Helios, which runs Cadence's remove passes. Every edge tensor is therefore contiguous and a memory format has no runtime representation. The emitter accepts only contiguous and preserve. The upstream `RemoveCloneOpsTransform` deliberately keeps clones that change memory format, because with dim order they carry a real layout, and Cadence's wrapper `RemoveCloneOpsTransformImported` ran it unchanged. Nothing removed the clone.

The wrapper becomes one pass, renamed `RemoveCloneOpsPass`: a `RemoveCloneOpsTransform` subclass that also treats an `aten.clone` with any memory format as a plain copy, so the clone is removed. `_clone_dim_order` keeps the upstream behavior. Dead-code elimination still runs afterwards, as it did in the wrapper. The upstream transform is unchanged.

The rename touches every caller in fbcode and xplat: Cadence passes, Helios sharding transforms, Jarvis, the SAS compiler and the xr_sonic gleam export. This replaces the Helios-only `StripCloneMemoryFormat` pass from the earlier version of this diff.

Differential Revision: D125145150
…ytorch#24319)

Summary:

`impl::G3::native::cat_out` declared variable-length arrays sized by the number of inputs (about 76 B per input) before it checked whether the `xa_nn_cat` path applies. A 256-input int64 cat in RT-DETR (`rtdetr_r18vd`, int8) therefore grew the frame by about 19 KB on the DSP thread that runs the operator, overflowed that thread's 7488 B stack and tripped the Zephyr stack sentinel on the first inference. Raising the stack did not help: 8 KB, 11.5 KB and 16 KB stacks all overflowed.

The nnlib path now runs only for same-dtype, supported-dtype cats with at most 16 inputs, and uses fixed-size arrays. Larger cats take the existing generic loop. The frame is a fixed 1440 B: the number of dynamic stack adjustments in `cat_out` goes from 11 to 0 in the built DSP image.

Adds a 40-input `cat` test case so the fallback branch is covered.

The 256 inputs are one tensor repeated: every entry of that cat references the same value and buffer. RT-DETR's decoder gathers with `topk_ind.unsqueeze(-1).repeat(1, 1, d_model)`, and Cadence's `ReplaceRepeatWithCatPass` lowers a `repeat` as a cat of the same tensor, so `d_model` = 256 becomes a 256-entry cat. The kernel is still the place to fix the overflow: the arrays are sized by entry count, not by distinct tensors, and a 100-entry cat of distinct inputs (EfficientDet-Lite0's full graph) would need about 7.6 KB of them, more than the whole 7488 B stack. Lowering `repeat` as a broadcast copy would remove RT-DETR's long list but leave genuinely wide cats exposed, so it is at most a later optimization.

Differential Revision: D128236590
@meta-codesync meta-codesync Bot changed the title Keep cat_out's nnlib input arrays off variable-length stack arrays Keep cat_out's nnlib input arrays off variable-length stack arrays (#24319) Nov 2, 2026

This branch was previously deployed

1 inactive deployment
cadence — bec367ba Deployed Nov 2, 2026 by zonglinpeng via hifi-op-test / hifi4 #36011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. meta-exported

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant