QNN sharded LLM export fails: ResolveDebugHandle is not the last edge pass (dep_table entry overwritten by SplitGraph registration)
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
Issue này chưa được đánh giá.
Mô tả
🐛 Describe the bug
Exporting any sharded LLM through the QNN static-llama flow (num_sharding > 1, i.e. every model ≥ ~3B such as llama3_2-3b_instruct, or a Qwen3-4B registered locally) fails with:
AssertionError: Please ensure ResolveDebugHandle is the last executed edge pass.
File "backends/qualcomm/_passes/qnn_pass_manager.py", line 432, in _validate_edge_passes
Non-sharded models (Qwen3 0.6B/1.7B, etc.) export fine, which is probably why CI has not caught this.
Root cause
When sharding is enabled, the dynamically created SplitGraph pass is registered like this (3 call sites):
dep_table[SplitGraph] = [FoldQDQ]
dep_table[TagQuantIO] = [SplitGraph] # <-- overwrites TagQuantIO: [LayoutTransform]
examples/qualcomm/oss_scripts/llama/wrappers/llm_wrappers.py(two sites)examples/models/llama/export_llama_lib.py(_export_llama, QNN branch)
The assignment replaces the pre-existing entry TagQuantIO: [LayoutTransform] from get_passes_dependency_for_capture_program(), silently dropping the LayoutTransform → TagQuantIO constraint. With that edge gone, the topological solver schedules TagQuantIO (and transitively ResolveDebugHandle, whose only constraint is "after TagQuantIO") too early, so ResolveDebugHandle is no longer last and the (recently added) _validate_edge_passes assertion fires.
Broken schedule tail: ... → ResolveDebugHandle → AnnotateGetAttr → InsertCastForFpActQuantizedWeight
Minimal repro (no device, no weights, runs in seconds):
from torch.fx.passes.infra.pass_manager import this_before_that_pass_constraint
from executorch.backends.qualcomm._passes import FoldQDQ, TagQuantIO
from executorch.backends.qualcomm._passes.qnn_pass_manager import get_qnn_pass_manager_cls
from executorch.extension.llm.custom_ops import model_sharding
cls = get_qnn_pass_manager_cls()
pm = cls()
passes_job = cls.get_capture_program_passes()
dep_table = cls.get_passes_dependency_for_capture_program()
SplitGraph, setting = model_sharding.get_split_graph_pass(36, shares=4, pattern=r"^layers\.(\d+)")
passes_job[SplitGraph] = setting
dep_table[SplitGraph] = [FoldQDQ]
dep_table[TagQuantIO] = [SplitGraph] # verbatim from the call sites above
for that, these in dep_table.items():
for this in these:
pm.add_constraint(this_before_that_pass_constraint(this, that))
for p in passes_job:
pm.add_pass(p)
pm.solve_constraints()
order = [getattr(p, "__name__", str(p)) for p in pm.passes]
assert order[-1] == "ResolveDebugHandle", f"tail: {order[-3:]}" # fails on main
End-to-end repro: python examples/qualcomm/oss_scripts/llama/llama.py --decoder_model llama3_2-3b_instruct ... (any sharded model).
Proposed fix (PR to follow):
- Call sites: append instead of overwrite —
dep_table.setdefault(TagQuantIO, []).append(SplitGraph). - Structural guarantee in
QnnPassManager.get_to_edge_transform_passes: constrainResolveDebugHandleafter every other pass inpasses_job, so dynamically registered passes can never be scheduled after it. This keeps the invariant that_validate_edge_passesasserts, instead of relying on call sites to remember it.
Verified: with the fix, a sharded Qwen3-4B (16a4w, 4 shards) exports and runs on SM8650 (113.8 tok/s prefill, 7.24 tok/s decode), and TestQNNQuantizedOperator.test_qnn_backend_abs --enable_x86_64 passes.
Found and analyzed with AI assistance (Claude Code).
Versions
- executorch: main @ 5e21c13cc9e34fa2922d5708ba5962e3e365afdb (2026-10-05)
- QNN SDK: 2.37.0.250724, SoC: SM8650 (HTP v75)
- torch 2.14.0+cpu, Python 3.11, Ubuntu (Linux 5.15)
cc @cbilgin @psiddh @larryliu0820 @mergennachin @cccclai @helunwencser @jackzhxng @digantdesai
- Ngôn ngữ chính
- Python
- Star
- 5.1k
- Fork
- 1.2k
- Merge trung bình
- 2 ngày 9 giờ
- Pull request đã merge (30 ngày)
- 632
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của pytorch/executorch
-
Portable remainder kernel: wrong sign for integers and float64 rounded to floatCó thể đã có người làm @usmanmateen đã nhận 1 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
pytorch/executorch#23682 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement triaged
Độ khó 2/5 Nửa ngày Mức phù hợp với người mới 68/100
pytorch/executorch#21640 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Portable floor_divide returns non-whole numbers for floats and wrong values for a zero divisorCó thể đã có người làm @usmanmateen đã nhận 1 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 52/100
pytorch/executorch#23684 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
torch.var_mean and torch.std_mean fail in to_edge: aten.var_mean.correction is not core ATen and has no core decompositionCó thể đã có người làm @usmanmateen đã nhận 1 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 58/100
pytorch/executorch#23680 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Prompts of max_seq_len tokens fail to prefill: export_llm bounds the KV-cache token input at max_seq_len - 1 but publishes get_max_seq_len = max_seq_lenCó thể đã có người làm @alpharomercoma đã nhận 2 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 20/100
pytorch/executorch#23678 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của pytorch/executorch
Issue tương tự
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 82/100
esphome/esphome.io#7657 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
comp/gateway comp/plugins duplicate P3 type/bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
NousResearch/hermes-agent#137019 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Kumo-Tabular weights unreachable behind restrictive egress proxies (Xet + plain HTTP both fail)Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
NVIDIA/structured-data-models#1091 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[work-item] adam-adae-worsening-emergence: conform spec.yaml to the specification style contract (REQ-1280)Có thể đã có người làm @muse-yamaa-bot đã nhận hôm nay. Đang mởwork-item
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày