Skip to content

Validate DynamicQuantizeLSTM recurrence quantization parameter shapes - #29254

Merged
Ti-Tai Wang (titaiwangms) merged 2 commits into
microsoft:mainfrom
titaiwangms:validate-dynamicquantizelstm-recurrence-shapes
Jul 8, 2026
Merged

Validate DynamicQuantizeLSTM recurrence quantization parameter shapes#29254
Ti-Tai Wang (titaiwangms) merged 2 commits into
microsoft:mainfrom
titaiwangms:validate-dynamicquantizelstm-recurrence-shapes

Conversation

@titaiwangms

Copy link
Copy Markdown
Contributor

Description

The R_zero_point / R_scale (recurrence) quantization-parameter shape validation in DynamicQuantizeLSTM was inadvertently checking the W (input) quantization parameters instead of the R ones. This change validates the R parameters' own shapes symmetrically with W, so malformed recurrence quantization parameters are rejected with a clear error.

Changes

  • Fix the shape checks so R_zero_point and R_scale are validated against the R tensor's expected shape (previously bound to the W tensor).
  • Add two expect-failure unit tests covering inconsistent recurrence zero-point and scale shapes.

Motivation

Improves input validation and error diagnostics for malformed DynamicQuantizeLSTM recurrence quantization parameters. CPU-only; no behavior change for valid inputs.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

…er shapes

The recurrence zero-point (R_zero_point) and scale (R_scale) inputs were not run
through the kernel's shape validation: R_zp_shape was bound to w_zp->Shape()
instead of r_zp->Shape(), and the R_scale WeightCheck was passed W_scale_shape
instead of R_scale_shape. As a result a malformed r_zp/r_scale (e.g. a shape
inconsistent with R) was never rejected and downstream code iterated using the
input parameter's element count over the recurrence parameter's buffer.

Bind R_zp_shape to r_zp->Shape() and validate R_scale against R_scale_shape so
the recurrence parameters are checked symmetrically with the input (W) ones.
Add two expect-failure tests that supply R_zero_point / R_scale shapes whose
first dimension does not match num_directions and assert the specific
INVALID_ARGUMENT diagnostics. Status-based validation, so the tests need no
ORT_NO_EXCEPTIONS guard. CPU-only op; no CUDA implementation exists.

Agent-signed-off: Developer (0b207188) [claude-opus-4.8 via copilot]
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a bug in the CPU DynamicQuantizeLSTM kernel’s input validation where recurrence quantization parameters (R_scale/R_zero_point) were mistakenly validated using the input-weight (W) parameter shapes. It also adds unit tests to ensure malformed recurrence quantization parameter shapes are rejected with a clear error.

Changes:

  • Correct R_zero_point shape validation to use r_zp->Shape() (instead of w_zp->Shape()).
  • Correct R_scale shape validation to use R_scale_shape (instead of W_scale_shape).
  • Add two negative tests that expect failures for inconsistent R_zero_point / R_scale shapes.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
onnxruntime/contrib_ops/cpu/quantization/dynamic_quantize_lstm.cc Fixes the recurrence quantization-parameter shape checks to validate against the actual R_* tensor shapes.
onnxruntime/test/contrib_ops/quantize_lstm_op_test.cc Adds expect-failure tests that confirm incorrect R_scale/R_zero_point shapes are rejected with the intended error message.

@yuslepukhin

Copy link
Copy Markdown
Contributor

Missing Tests

  • Per-channel (2D) shape mismatch on dim[1] — Both new tests only exercise the per-tensor (1D) path with a wrong first dimension. No test supplies a 2D shape where dim[0] is correct but dim[1] != 4hidden_size (e.g., {1, 3} when 4hidden_size == 8). This would exercise the second condition in WeightCheck.

  • Valid R-parameter shapes that differ from W shapes — A positive test where W is per-tensor {1} but R is per-channel {1, 8} (or vice versa) would confirm that the now-independent validation doesn't accidentally reject valid asymmetric configurations.

  • Bidirectional case (num_directions == 2) — All negative tests use num_directions == 1. A test with bidirectional direction and R_scale / R_zero_point having dim[0] == 1 (should fail) would strengthen coverage.

  • ZeroPointCheck coverage for R — The ZeroPointCheck macro (line 146) also uses R_zp_shape (which was previously wrong). A test where R_zero_point has the correct shape but non-constant values (for unsigned) would verify the value-level check now runs on the correct data.

Add the maintainer-requested test coverage for the recurrence
quantization-parameter validation:

- Per-channel (2D) recurrence shape mismatch on the second dim
  (correct num_directions first dim, wrong 4*hidden_size second dim),
  exercising the per-channel branch of the shape check.
- Positive mixed-granularity case (per-tensor W with per-channel R and
  vice versa) that runs to completion, confirming valid mixed configs
  are not falsely rejected.
- Bidirectional (num_directions == 2) recurrence shape mismatch.
- Per-channel recurrence zero-point with correct shape but non-constant
  values, exercising the per-element zero-point validation against R's
  own shape and values.

Generalize RunQuantLSTM/ComputeRefOutput to accept independent W and R
quantization granularity (the convenience wrapper preserves the existing
symmetric behavior) and extend the expect-failure helper with
num_directions and optional recurrence zero-point values.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants