Qualcomm AI Engine Direct - HF LLM Performance and Accuracy Improvement - #21487
Qualcomm AI Engine Direct - HF LLM Performance and Accuracy Improvement#21487winskuo-quic wants to merge 7 commits into
Conversation
Align the HF decoder wrapper's token input dtype with static_llama (int32 instead of int64) for both the exported graph signature and the calibration loop. The shared qnn_llama_runner auto-detects the token dtype and narrows accordingly, so no runner change is needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
annotate_kv_8bit_hf tags the KV-cache concat and its graph IO 8-bit for the HF decoder flow, matching static_llama's annotate_kv_8bit. The HF wrapper keeps K stored non-transposed with boundary transposes in forward(), so the walk also traverses the past-KV branch backward (to the K/V placeholder) and the new-KV branch forward (to the K/V graph output) through the pass-through transposes, so both the input and output boundaries are tagged 8-bit. Wire it into pt2e_quantize and set kv_type=uint8 for the 16a*w configs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
HF computes RoPE inside the traced graph, so the inv_freq math becomes a quantization target. For rope_type=llama3 (llama3.2) inv_freq spans about seven orders of magnitude, and a single per-tensor scale cannot represent it: the low-frequency components that carry long-range position information collapse and the model degenerates into repetitive output under 16a8w. qwen2.5 escapes this only because its default RoPE range is roughly sixteen times tighter. Constant folding cannot help here because the cos/sin computation depends on position_ids, a runtime input. Instead, precompute the tables over the whole position domain [0, max_seq_len) on the host, the way static_llama does, and leave the graph with a gather. The tables are built by calling the original rotary embedding module so any rope_type, scaling and attention_scaling are honored exactly; cos/sin match the original bit-exactly. Only values bounded in [-1, 1] then enter the quantized graph. Removing the per-token inv_freq matmul, cos, sin and their quant/dequant nodes also cuts real work: llama3_2-1b at 16a8w, CL=128 goes from 35.1/31.4 to 49.6/45.9 tokens per second for prefill/decode, and the output is coherent again. fp16 stays coherent. Also align the attention mask fill value with static_llama's PADDING_MASK_VALUE. MHA-to-SHA is left disabled; it still produces a graph HTP rejects. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/21487
Note: Links to docs will display an error until the docs builds have been completed. ❌ 2 New FailuresAs of commit 6b07734 with merge base 39f4355 ( NEW FAILURES - The following jobs have failed:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a
|
| logging.warning("No rotary_emb found; skipping RoPE precompute.") | ||
| return | ||
| # HF API does not have a way to replace, so manually replace it. | ||
| decoder.rotary_emb = QnnPrecomputedRotaryEmbedding( |
There was a problem hiding this comment.
Rope manual override.
| return self.max_cache_len, 0 | ||
|
|
||
|
|
||
| class QnnCustomStaticCache(Cache): |
There was a problem hiding this comment.
QNN Custom Cache
Summary
python examples/qualcomm/oss_scripts/hf_causal_lm.py --prompt "Simply put, the theory of relativity states that" --soc_model SM8750 --device $DEVICE_ID --build_folder build-android/ --decoder_model llama3_2-1b --max_seq_len 128 --ptq 16a8wTest plan
[PLEASE REMOVE] How did you test this PR? Please write down any manual commands you used and note down tests that you have written if applicable.