Skip to content

Support int16 in vision quantized_layer_norm (#24094) - #24094

Open
mvartani-meta wants to merge 3 commits into
pytorch:mainfrom
mvartani-meta:export-D126953450
Open

mvartani-meta wants to merge 3 commits into
pytorch:mainfrom
mvartani-meta:export-D126953450

Conversation

@mvartani-meta

@mvartani-meta mvartani-meta commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

The vision quantized_layer_norm kernel only handled uint8 and int8; int16 input aborted at its ET_CHECK_MSG. It also had the same precision problems as the HiFi and generic kernels:

  • int32 accumulators, which overflow for int16 because one squared value can reach 2^30.
  • An E[x^2] - E[x]^2 variance, which cancels catastrophically when the mean is large compared to the spread.

This kernel is registered for Cadence Vision builds through functions_vision.yaml. This change closes the last int16 gap among the Cadence layer norm kernels.

Changes:

  • Add an int16 (Short) branch to both overloads.
  • Accumulate in int64 for 16-bit types; 8-bit keeps int32 in the inner loop.
  • Widen to the accumulator type before squaring, so the product cannot overflow int32.
  • Apply the zero-point correction in int64 and compute the variance numerator N*sum(v^2) - sum(v)^2 exactly in integers. The per-row mean and variance stay in double as before.
  • Declare both kernels in vision/operators/operators.h.

Reviewed By: DrJessop

Differential Revision: D126953450

@pytorch-bot

pytorch-bot Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ No Failures

As of commit 3bc9a24 with merge base 2c3e231 (image):
💚 Looks good so far! There are no failures yet. 💚

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 22, 2026
@meta-codesync

meta-codesync Bot commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

@mvartani-meta has exported this pull request. If you are a Meta employee, you can view the originating Diff in D126953450.

@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.

@meta-codesync meta-codesync Bot changed the title Support int16 in vision quantized_layer_norm Support int16 in vision quantized_layer_norm (#24094) Oct 22, 2026
mvartani-meta added a commit to mvartani-meta/executorch that referenced this pull request Oct 22, 2026
Summary:

The vision quantized_layer_norm kernel only handled uint8 and int8; int16 input aborted at its ET_CHECK_MSG. It also had the same precision problems as the HiFi and generic kernels:
- int32 accumulators, which overflow for int16 because one squared value can reach 2^30.
- An E[x^2] - E[x]^2 variance, which cancels catastrophically when the mean is large compared to the spread.

This kernel is registered for Cadence Vision builds through functions_vision.yaml. This change closes the last int16 gap among the Cadence layer norm kernels.

Changes:
- Add an int16 (Short) branch to both overloads.
- Accumulate in int64 for 16-bit types; 8-bit keeps int32 in the inner loop.
- Widen to the accumulator type before squaring, so the product cannot overflow int32.
- Apply the zero-point correction in int64 and compute the variance numerator N*sum(v^2) - sum(v)^2 exactly in integers. The per-row mean and variance stay in double as before.
- Declare both kernels in vision/operators/operators.h.

Reviewed By: DrJessop

Differential Revision: D126953450
mvartani-meta added a commit to mvartani-meta/executorch that referenced this pull request Oct 22, 2026
Summary:

The vision quantized_layer_norm kernel only handled uint8 and int8; int16 input aborted at its ET_CHECK_MSG. It also had the same precision problems as the HiFi and generic kernels:
- int32 accumulators, which overflow for int16 because one squared value can reach 2^30.
- An E[x^2] - E[x]^2 variance, which cancels catastrophically when the mean is large compared to the spread.

This kernel is registered for Cadence Vision builds through functions_vision.yaml. This change closes the last int16 gap among the Cadence layer norm kernels.

Changes:
- Add an int16 (Short) branch to both overloads.
- Accumulate in int64 for 16-bit types; 8-bit keeps int32 in the inner loop.
- Widen to the accumulator type before squaring, so the product cannot overflow int32.
- Apply the zero-point correction in int64 and compute the variance numerator N*sum(v^2) - sum(v)^2 exactly in integers. The per-row mean and variance stay in double as before.
- Declare both kernels in vision/operators/operators.h.

Reviewed By: DrJessop

Differential Revision: D126953450
Summary:

The HiFi quantized_layer_norm kernels dispatched with ET_FORALL_CADENCE_QUANTIZED_TYPES, so int16 inputs fell through to ET_DCHECK_MSG. That check compiles out in release builds, which left the output tensor unwritten and produced garbage numerics for int16 models.

Simply widening the dispatch is not enough because the statistics used int32 accumulators. For int16, a single squared value can reach 2^30, so sq_sum overflows after two elements. The variance was also computed as E[x^2] - E[x]^2 in fp32, which cancels catastrophically when the mean is large relative to the spread.

Changes:
- Dispatch both overloads with ET_FORALL_CADENCE_QUANTIZED_TYPES_WITH_INT16.
- Accumulate sum and sq_sum in int64 for 16-bit types. 8-bit types keep int32 in the inner loop.
- Widen to the accumulator type before squaring, so the product cannot overflow int32.
- Apply the zero-point correction in int64 and compute the variance numerator N*sum(v^2) - sum(v)^2 exactly in integers before converting to float. For 8-bit this is equal or more accurate than before.
- Declare quantized_layer_norm_out and quantized_layer_norm_per_tensor_out in operators.h and add a gtest.

Reviewed By: DrJessop

Differential Revision: D126939431
Summary:

The generic quantized_layer_norm kernel has the same int16 gap as the HiFi kernel fixed earlier in this stack. The generic kernel is the portable implementation used on CPU and on Xtensa cores that have no backend-specific layer norm kernel.

Before this change, both overloads dispatched with ET_FORALL_CADENCE_QUANTIZED_TYPES, so int16 fell through to an ET_DCHECK_MSG that compiles out in release builds and left the output unwritten. The statistics also used int32 accumulators, which overflow for int16 because one squared value can reach 2^30. The variance was formed as E[x^2] - E[x]^2, which cancels catastrophically when the mean is large compared to the spread.

This applies the same fix as the HiFi kernel:
- Dispatch both overloads with ET_FORALL_CADENCE_QUANTIZED_TYPES_WITH_INT16.
- Accumulate in int64 for 16-bit types; 8-bit keeps int32 in the inner loop.
- Widen to the accumulator type before squaring, so the product cannot overflow int32.
- Apply the zero-point correction in int64 and compute the variance numerator N*sum(v^2) - sum(v)^2 exactly in integers. The per-row mean and variance stay in double as before.
- Add a gtest with the same hand-computed cases as the HiFi test.

Reviewed By: DrJessop

Differential Revision: D126951724
Summary:

The vision quantized_layer_norm kernel only handled uint8 and int8; int16 input aborted at its ET_CHECK_MSG. It also had the same precision problems as the HiFi and generic kernels:
- int32 accumulators, which overflow for int16 because one squared value can reach 2^30.
- An E[x^2] - E[x]^2 variance, which cancels catastrophically when the mean is large compared to the spread.

This kernel is registered for Cadence Vision builds through functions_vision.yaml. This change closes the last int16 gap among the Cadence layer norm kernels.

Changes:
- Add an int16 (Short) branch to both overloads.
- Accumulate in int64 for 16-bit types; 8-bit keeps int32 in the inner loop.
- Widen to the accumulator type before squaring, so the product cannot overflow int32.
- Apply the zero-point correction in int64 and compute the variance numerator N*sum(v^2) - sum(v)^2 exactly in integers. The per-row mean and variance stay in double as before.
- Declare both kernels in vision/operators/operators.h.

Reviewed By: DrJessop

Differential Revision: D126953450

This branch was successfully deployed

1 active deployment
cadence — 3bc9a240 Deployed Oct 22, 2026 by mvartani-meta via hifi-op-test / hifi4 #34430
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.

2 participants