Repository navigation
Keep cat_out's nnlib input arrays off variable-length stack arrays (#24319) - #24319
zonglinpeng wants to merge 2 commits into
Conversation
🔗 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. ✅ No FailuresAs of commit 596866a with merge base dd01cb4 ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
@zonglinpeng has exported this pull request. If you are a Meta employee, you can view the originating Diff in D128236590. |
This PR needs a
|
ea355db to
bec367b
Compare
…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
…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
bec367b to
ab5263b
Compare
4f10610 to
437158c
Compare
…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
437158c to
7849b29
Compare
…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
…aces (pytorch#24453) Summary: `rlx_arbitrary_image_stylization` fails in the ExecuTorch emitter: `InternalError: Tensor has a memory_format that is unsupported in ExecuTorch: torch.channels_last`. Its lowered graph carries `clone(memory_format=torch.channels_last)` on ops that stay on the CPU, the program is lowered with `_skip_dim_order=True`, and the emitter accepts only `contiguous_format` and `preserve_format` for an `aten.clone`. `RemoveCloneOpsTransform` now runs in two steps: 1. Every `aten.clone` and `aten._to_copy` whose only effect is a non-contiguous `memory_format` is deleted. These ops carry a layout only in programs lowered with `_skip_dim_order=True`, where the emitter cannot represent one. Dim-order copies (`_clone_dim_order`, `_to_dim_order_copy`) describe a layout the runtime honours, so XNNPACK and other dim-order users keep them; they only go through step 2. The graph is then retraced, so every node's `meta["val"]` carries the dim order it has without those copies. A copy that also converts the dtype is kept. Args are read with `get_arg`, so a positional `memory_format` is handled too. - A copy that produces a graph output is not deleted. After the retrace, if its input does not already have the copy's layout, the transform raises: deleting it would change the layout callers expect for that output. This includes input-to-output copies under `preserve_input_output_copies`, which used to be skipped and then failed in the emitter. - An output copy whose input already has that layout is an identity. It goes to step 2, which still honours `preserve_input_output_copies`. 2. The existing clean-up runs on the retraced graph: `preserve_format` clones and clones of an input already in the requested layout are removed. A contiguous clone of an input that is not contiguous, such as a channels-last placeholder, stays. The retrace only runs when step 1 deleted something, so graphs without layout copies go through exactly the old path. This replaces this diff's earlier approach, which rewrote a channels-last `aten.clone` into a contiguous copy. Reviewed By: DrJessop 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
7849b29 to
596866a
Compare
Summary:
impl::G3::native::cat_outdeclared variable-length arrays sized by the number of inputs (about 76 B per input) before it checked whether thexa_nn_catpath 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_outgoes from 11 to 0 in the built DSP image.Adds a 40-input
cattest 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'sReplaceRepeatWithCatPasslowers arepeatas a cat of the same tensor, sod_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. Loweringrepeatas 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