Qualcomm AI Engine Direct - HF LLM Optimization Stage 1 - #22170
Qualcomm AI Engine Direct - HF LLM Optimization Stage 1#22170winskuo-quic wants to merge 2 commits into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/22170
Note: Links to docs will display an error until the docs builds have been completed. ✅ No FailuresAs of commit 1a317f2 with merge base d750618 ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a
|
8fdf21c to
79a710f
Compare
| from torchao.quantization.pt2e import MinMaxObserver | ||
|
|
||
|
|
||
| class HFLLMQuantRecipe: |
There was a problem hiding this comment.
This class/file need not be named as "HF". This is how we want the Quant recipe to be applied in any non-static llama flow. This is our eventual target. linear to conv is a graph change that should happen during lowering or to_backend() stage
There was a problem hiding this comment.
Also, isn't this supposed to be an abstract class?
There was a problem hiding this comment.
This class/file need not be named as "HF". This is how we want the Quant recipe to be applied in any non-static llama flow. This is our eventual target. linear to conv is a graph change that should happen during lowering or to_backend() stage
Sounds good. I have removed HF from the receipe class and file name.
For the linear_to_conv explanation at top, I forgot to remove that when updating the linear_to_conv behavior to annotation_pass, so we actually target conv node in recipe instead of linear. Thanks for the catch here.
I have removed the linear_to_conv expplanation since you have mentioned all non-static-llama flow uses this file, which means other flow can turn off linear_to_conv
There was a problem hiding this comment.
Also, isn't this supposed to be an abstract class?
I believe it was abstract in runtime behavior but not in declaration.
I have changed to abstract class now.
I only changed this file and not static_llm_quant_recipe.py since it is out of scope of this PR.
| self.recipe: Optional[QuantRecipe] = None | ||
|
|
||
| # For IO bitwidth | ||
| self.default_quant_dtype = getattr(self, "default_quant_dtype", None) |
There was a problem hiding this comment.
can you check how different the Quant config with GenAI refactor as well as the LLM Config integration is. It would be nice to align or be close before creating this interface
There was a problem hiding this comment.
I have checked GenAI flow and believe this should be fine. GenAI flow as it is still reusing quant recipe logic.
| @@ -162,16 +163,15 @@ def get_default_pass_activations(cls): | |||
| ] | |||
|
|
|||
| @classmethod | |||
| def get_annotation_passes(cls): | |||
| def get_annotation_passes(cls, convert_linear_to_conv2d: bool = False): | |||
There was a problem hiding this comment.
Adding such flags one at a time is not very scalable. Also, get is trying to return list of passes while passing flags seems to already have knowledge of what passes are present. This seems inverted. Specific passes can be disabled by the caller as needed after get()
There was a problem hiding this comment.
I totally agree with you, and this is actually on my list too.
Worth noting how deep it goes: the parameter is threaded through five layers, and the GPU override accepts it without ever reading it, since annotation is skipped for GPU entirely.
Doing it properly means a design refactor of the annotation pass pipeline, and I'd like to keep this PR focused on the HF optimizations with minimal changes to pass structure. I think it makes more sense to target it in a follow-up PR.
| False, | ||
| act_observer=MinMaxObserver, | ||
| granularity=QuantGranularity.PER_BLOCK, | ||
| extra_kwargs={"block_size": (1, 16, 1, 1)}, |
There was a problem hiding this comment.
can we replicate the "note" from Llama3_2_1B_HFQuantRecipe in all the recipes
There was a problem hiding this comment.
Added to all other recipes.
Summary
As HF use case is increasing, we aim to align accuracy and performance of HF LLM with Static LLM(static_llama.py).
Currently, there are many gaps, and we have a series of PR to fill the gaps.
For now, we will first focus on Llama3.2 1B decode mode.
What is done
examples/qualcomm/oss_scripts/llm_utils/hf_llm_quant_recipe.py. The quantization technique is mostly migrated fromexecutorch/examples/qualcomm/oss_scripts/llama/static_llm_quant_recipe.py, with some minor changes, especially the weight naming as HF-LLM and Static-LLM structure naming is different.seq_len. This increases the memory consumption and is also bad for performance. To resolve this issue, we have implementedQnnCustomStaticCacheso mode now only outputs the new pair of kv-cache.inv_freqAdditionally, since we are precomputing rope, we can also improve performance.annotate_kv_8bitin the mainline. This issue is happens during v_proj linear node. When these 2 are used together, thepermuteandview_copywill be tagged as 16bit, so it becomes conv(16bit) ->permute(16bit) -> view_copy(16bit) -> cast(8bit). This is bad and different from static llama since if we insert cast(8bit) right after conv(16bit), rest of the ops can run in 8bits, which is faster. After this change, the behavior now aligns with static llama, which is conv(16bit) -> cast(8bit) ->permute(8bit) -> view_copy(8bit).Optimization Result Compared with Llama3.2 1B_instruct (HF uses non-instruct verison)
For now, accuracy is not compared as HF flow has not yet support SQNR evaluation. Official accuracy features will be supported in Upcoming PRs. However, this PR did ensure HF output is reasonable and readable.
Sample Script
python examples/qualcomm/oss_scripts/hf_causal_lm.py --prompt "Simply put, the theory of relativity states that" --soc_model SM8750 --device $DEVICE --build_folder build-android/ --decoder_model llama3_2-1b --max_seq_len 1024Upcoming Features
Performance & Accuracy
Feature
Test plan
pytest backends/qualcomm/tests/rework/passes/test.py -k "test_fuse_consecutive_reshape"pytest backends/qualcomm/tests/rework/passes/test.py -k "test_convert_linear_to_conv2d"python backends/qualcomm/tests/test_qnn_delegate.py TestExampleLLMScript.test_hf_causal_lm --device $DEVICE--soc_model SM8750 --build_folder build-android --executorch_root . --artifact_dir ./llama3_2_1b --model_name llama3_2-1b