pytorch / pytorch/executorch

Preserve ExportedProgram dynamic input shape constraints in .pte for runtime/backend validation

Open
#20,066 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

module: runtime
Dominant language
Python
Stars
5k
Forks
1.2k
Avg merge
2d 10h
Merged PRs (30d)
581

Description

🚀 The feature, motivation and pitch
Problem

torch.export can represent a rich input shape contract for dynamic-shape models. This contract is enforced when running:

exported_program.module(check_guards=True)

because the returned module includes guard logic, such as _guards_fn, that validates real inputs before executing the graph.

However, after lowering to ExecuTorch and serializing to .pte, only a much weaker form of shape metadata appears to survive:

  • Tensor.sizes
  • Tensor.shape_dynamism
  • Tensor.dim_order

For DYNAMIC_BOUND, Tensor.sizes stores the upper-bound shape. The richer input shape contract from ExportedProgram does not appear to have an equivalent runtime representation in the .pte.

Example

Given:

half_height = torch.export.Dim("half_height", min=4, max=8)
height = 2 * half_height

dynamic_shapes = (
  {
    2: height,
    3: torch.export.Dim("width", min=8, max=16),
  },
)

The exported program contains symbolic placeholder shapes such as:

x: [1, 3, 2*s87, s46]

and range constraints such as:

2*s87: min=8, max=16
s87:   min=4, max=8
s46:   min=8, max=16

When executing the exported module eagerly, the guard logic rejects invalid inputs. For example, an input with height 9 is rejected because 9 cannot be represented as 2*s87 for an integer s87:

Expected input *args[0].shape[2] = 9 to be of the form 2*s87, where s87 is an integer. However after serializing to .pte, the input tensor metadata contains only:

sizes=[1, 3, 16, 16]
shape_dynamism=DYNAMIC_BOUND

This preserves the upper bound, but not the fact that height must be even, nor the lower bound, symbolic expression, or root-symbol range.

Why this matters

Backends that support dynamic shapes may need to validate input shapes before compilation, specialization, or execution.

If the .pte only exposes upper-bound tensor sizes, a backend cannot reliably recover the original valid input shape domain. This can lead to late failures, poor error messages, or backend/compiler crashes when an invalid dynamic input shape is accepted by ExecuTorch but rejected deeper in backend-specific code.

This is not specific to one backend. Any delegate backend that consumes a dynamic-shape lowered graph may need access to the same input shape contract that ExportedProgram.module(check_guards=True) enforces in eager execution.

Question

What is the intended mechanism for preserving and enforcing the ExportedProgram input shape contract after lowering to ExecuTorch?

Should ExecuTorch:

  1. Serialize a normalized input shape-constraint representation into the .pte?
  2. Preserve ExportedProgram.range_constraints plus symbolic placeholder shape expressions in the runtime program?
  3. Provide a standard backend API for extracting and serializing this contract into delegate payloads?
  4. Provide runtime utilities for validating actual inputs against the exported shape contract before delegate execution?
  5. Intentionally expose only Tensor.shape_dynamism and upper-bound Tensor.sizes, leaving full validation to individual backends?
Desired outcome

It would be helpful to clarify or standardize how dynamic shape constraints are preserved across:

torch.export.ExportedProgram -> ExecuTorch lowering -> .pte serialization -> runtime/backend execution

Ideally, .pte or backend delegate metadata would preserve enough information to validate the same input shape contract enforced by ExportedProgram.module(check_guards=True), including:

  • rank checks
  • static dimensions
  • min/max range constraints
  • symbolic equality relationships
  • derived symbolic expressions such as 2*s
  • guard-derived constraints that affect valid input shapes

This does not necessarily mean serializing _guards_fn itself. A normalized, runtime-friendly shape-constraint representation may be more appropriate.

Alternatives

No response

Additional context

No response

RFC (Optional)

No response

cc @larryliu0820 @JacobSzwejbka @lucylq

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the ExportedProgram range_constraints and symbolic placeholder shapes through ExecuTorch lowering and .pte serialization, then examine runtime/backend execution. Done means defining and documenting whether the serialized program or delegate metadata preserves enough of the input shape contract for validation, including relationships and bounds.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, pytorch
Domain
ai, backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.