Skip to content

Qualcomm AI Engine Direct - LPAI Support Partition#19835

Merged
psiddh merged 2 commits into
pytorch:mainfrom
CodeLinaro:dev1/winskuo/gh/lpai/support_partition
Jun 15, 2026
Merged

Qualcomm AI Engine Direct - LPAI Support Partition#19835
psiddh merged 2 commits into
pytorch:mainfrom
CodeLinaro:dev1/winskuo/gh/lpai/support_partition

Conversation

@winskuo-quic

@winskuo-quic winskuo-quic commented May 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Support LPAI to fallback ops to CPU.

Traditionally, when it gets to partial delegation for quantized model, we need to wrap qdq nodes around the unsupported node. e.g., supported_node_1(u8) -> dq(fp32) -> cpu_node(fp32) -> q(u8) -> supported_node_2.
All the nodes besides from cpu_node(fp32) is run on HTP.
However, LPAI's accuracy when computing dq and q node isn't as good as HTP, so to achieve good accuracy, we want to fallback q and dq nodes back to cpu too.
This PR is trying to achieve this while ensuring edge graph is a valid graph to PyTorch.

Test plan

A series of test validating cases to fallback multi-output node, multi-input node, contiguous fallback, etc.

python backends/qualcomm/tests/test_qnn_delegate.py -k TestQNNQuantizedUtils.test_qnn_backend_skip_node_id_partitioner --model SM8850 --device $DEVICE --build_folder build-android --seed 42 --backend lpai

python backends/qualcomm/tests/test_qnn_delegate.py -k TestQNNQuantizedUtils.test_qnn_backend_skip_node_op_partitioner --model SM8850 --device $DEVICE --build_folder build-android --seed 42 --backend lpai

cc @cccclai @cbilgin @abhinaykukkadapu

@pytorch-bot

pytorch-bot Bot commented May 28, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

❌ 2 New Failures

As of commit 863cebb with merge base ff2bf9c (image):

NEW FAILURES - The following jobs have failed:

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

@linux-foundation-easycla

linux-foundation-easycla Bot commented May 28, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

@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 May 28, 2026
@winskuo-quic winskuo-quic force-pushed the dev1/winskuo/gh/lpai/support_partition branch from 4e89627 to b5c9b66 Compare June 3, 2026 06:48
@psiddh psiddh added module: qnn Issues related to Qualcomm's QNN delegate and code under backends/qualcomm/ release notes: api Changes to public facing apis (any interfaces, pybinded runtime methods, etc.) release notes: qualcomm Changes to the Qualcomm backend delegate labels Jun 4, 2026
if node.target in q_ops or node.target in dq_ops:
continue
if node.meta.get(QCOM_FALLBACK_NODE):
assert all(

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.

It looks like insert_partition_qdq only wraps an input with a Q/DQ pair when that input is a call_function that has QCOM_QUANT_ATTRS (and isn't already a dq op). So only quantized tensor inputs get a DQ in front of them which makes sense, since you can't dequantize something like an int index or a shape arg.

But here the assert seems to require that every input of the fallback node is a dq op. So if a fallback node has an input that wasn't quantized, e.g. an integer/index input, an fp32 graph input, or a weight, wouldn't that be a problem ?

Do we have tests that actually validate fallback ops that are not fully-quantized tensors ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the code review and catching this.
This indeed will cause error when the tensor is other dtype such as int.
I have added a new UT and fix this issue.
The UT will fallback a node that is type integer and ensured it is working with the newest commit.

@psiddh

psiddh commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Can you resolve easy CLA and rebase to resolve conflicts please ?

@winskuo-quic winskuo-quic force-pushed the dev1/winskuo/gh/lpai/support_partition branch from b5c9b66 to 863cebb Compare June 10, 2026 05:02
@winskuo-quic

Copy link
Copy Markdown
Collaborator Author

Can you resolve easy CLA and rebase to resolve conflicts please ?

Hi @psiddh,
Thanks for the code review and identifying some issues.
I have fixed and rebased the PR.
Please have a look.
Thanks

@psiddh psiddh merged commit caf8e03 into pytorch:main Jun 15, 2026
176 of 178 checks passed
meta-codesync Bot pushed a commit that referenced this pull request Jun 17, 2026
…d fix for D108707519) (#20324)

Summary:

Forward fix for D108707519 (Qualcomm AI Engine Direct - LPAI Support Partition, #19835).

The new LpaiPartitionFallbackSupport pass crashes when run without QNN compiler
specs:

  lpai_partition_fallback_support.py:153 get_unsupported_nodes
    op_validator = QnnOperatorSupport(compiler_specs=self.compiler_specs, ...)
  TypeError: 'NoneType' object is not iterable

The edge-transform pass framework injects compiler_specs into passes but
defaults it to None (QnnPassManager.get_to_edge_transform_passes(compiler_specs=
None)). Lowering paths that run the edge transform without partitioner-supplied
specs — e.g. the modai LPAI offline-compile path
(modai/test:test_qualcomm_lpai_recipes::test_export_and_lower_8a8w_writes_pte) —
reach this pass with compiler_specs=None, and QnnOperatorSupport then iterates
the None specs and aborts the whole to_edge_transform_and_lower.

The pass fundamentally needs compiler specs to decide which nodes are LPAI-
unsupported, so with no specs there is nothing to validate against. Skip the
pass (return PassResult(.., modified=False)) in that case, restoring the
behavior from before this pass existed for spec-less paths. On-device paths that
do supply compiler_specs are unaffected.

Differential Revision: D108853837
Gasoonjia added a commit that referenced this pull request Jun 17, 2026
…d fix for D108707519) (#20324) (#20324)

Summary:

Forward fix for D108707519 (Qualcomm AI Engine Direct - LPAI Support
Partition, #19835).

The new LpaiPartitionFallbackSupport pass crashes when run without QNN
compiler
specs:

  lpai_partition_fallback_support.py:153 get_unsupported_nodes
op_validator = QnnOperatorSupport(compiler_specs=self.compiler_specs,
...)
  TypeError: 'NoneType' object is not iterable

The edge-transform pass framework injects compiler_specs into passes but
defaults it to None
(QnnPassManager.get_to_edge_transform_passes(compiler_specs=
None)). Lowering paths that run the edge transform without
partitioner-supplied
specs — e.g. the modai LPAI offline-compile path

(modai/test:test_qualcomm_lpai_recipes::test_export_and_lower_8a8w_writes_pte)
—
reach this pass with compiler_specs=None, and QnnOperatorSupport then
iterates
the None specs and aborts the whole to_edge_transform_and_lower.

The pass fundamentally needs compiler specs to decide which nodes are
LPAI-
unsupported, so with no specs there is nothing to validate against. Skip
the
pass (return PassResult(.., modified=False)) in that case, restoring the
behavior from before this pass existed for spec-less paths. On-device
paths that
do supply compiler_specs are unaffected.

Differential Revision: D108853837
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. module: qnn Issues related to Qualcomm's QNN delegate and code under backends/qualcomm/ release notes: api Changes to public facing apis (any interfaces, pybinded runtime methods, etc.) release notes: qualcomm Changes to the Qualcomm backend delegate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants