Skip to content

Commit c49a4d7

Browse files
committed
CPU QDQ SQNR support
1 parent e9a300a commit c49a4d7

4 files changed

Lines changed: 45 additions & 47 deletions

File tree

‎examples/qualcomm/oss_scripts/llama/decoder_constants.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
# This source code is licensed under the BSD-style license found in the
55
# LICENSE file in the root directory of this source tree.
66

7+
# decode qdq file name
8+
DECODE_QDQ_FILENAME = "decode_qdq.pt2"
9+
710
# eval methods
811
PROMPT_EVAL = "prompt_eval"
912
TASKS_EVAL = "tasks_eval"

‎examples/qualcomm/oss_scripts/llama/decoder_runtime_evaluator.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ def run(self, prompt):
389389
self.inference_speed = output_performance_holder[0]
390390

391391
sqnr = compute_error(golden_logits, output_logits_holder[0])
392-
return sqnr.item()
392+
return sqnr.item(), golden_logits, output_logits_holder[0]
393393

394394

395395
class TaskEval(EvalBase):

‎examples/qualcomm/oss_scripts/llama/llama.py‎

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
# TODO: reenable pyre after fixing the issues
88
# pyre-ignore-all-errors
99

10-
import copy
11-
import getpass
1210
import json
1311
import logging
1412
import os
@@ -17,26 +15,6 @@
1715
from typing import Dict
1816

1917
import torch
20-
from executorch.backends.qualcomm._passes import FoldQDQ, TagQuantIO
21-
from executorch.backends.qualcomm._passes.i64_to_i32 import I64toI32
22-
from executorch.backends.qualcomm._passes.qnn_pass_manager import (
23-
get_capture_program_passes,
24-
)
25-
from executorch.backends.qualcomm._passes.utils import (
26-
get_passes_dependency_for_capture_program,
27-
)
28-
29-
from executorch.backends.qualcomm.builders.utils import is_graph_output
30-
from executorch.backends.qualcomm.quantizer.custom_annotation import (
31-
annotate_prefill_kv_output,
32-
)
33-
34-
from executorch.backends.qualcomm.serialization.qc_schema import QcomChipset
35-
36-
from executorch.backends.qualcomm.utils.constants import (
37-
QCOM_PASS_ACTIVATE_KEY,
38-
QCOM_PASS_ARGS_KWARGS_DEFAULTS_KEY,
39-
)
4018
from executorch.backends.qualcomm.utils.utils import (
4119
generate_htp_compiler_spec,
4220
generate_qnn_executorch_compiler_spec,
@@ -49,6 +27,7 @@
4927
from executorch.examples.qualcomm.oss_scripts.llama.dataset import DatasetBuilder
5028
from executorch.examples.qualcomm.oss_scripts.llama.decoder_constants import (
5129
AUDIO_ENCODER,
30+
DECODE_QDQ_FILENAME,
5231
DECODER_GRAPH_NAMES,
5332
EVAL_MODE,
5433
PROMPT_EVAL,
@@ -65,33 +44,13 @@
6544
SqnrEval,
6645
TaskEval,
6746
)
68-
from executorch.examples.qualcomm.oss_scripts.llama.decoder_utils import (
69-
graph_module_inference,
70-
)
71-
from executorch.examples.qualcomm.oss_scripts.llama.model.static_llama import (
72-
LlamaModel,
73-
ModelArgs,
74-
)
75-
from executorch.examples.qualcomm.oss_scripts.llama.range_setting_pt2e import (
76-
make_custom_quantizer,
77-
)
78-
from executorch.examples.qualcomm.oss_scripts.llama.static_llm_quant_recipe import (
79-
StaticLLMQuantRecipe,
80-
)
8147
from executorch.examples.qualcomm.oss_scripts.llama.tokenizer import TokenizerWrapper
8248
from executorch.examples.qualcomm.oss_scripts.llama.wrappers import (
8349
MultiModalManager,
8450
next_power_of_two,
8551
)
86-
8752
from executorch.examples.qualcomm.utils import setup_common_args_and_variables
88-
from executorch.exir.capture._config import ExecutorchBackendConfig
89-
from executorch.exir.dialects._ops import ops as exir_ops
90-
from executorch.exir.passes.memory_planning_pass import MemoryPlanningPass
91-
from executorch.extension.llm.custom_ops import model_sharding
92-
from executorch.extension.llm.export.builder import DType
93-
from pytorch_tokenizers import get_tokenizer, TiktokenTokenizer
94-
from pytorch_tokenizers.llama2c import Llama2cTokenizer as SentencePieceTokenizer
53+
from torchao.quantization.utils import compute_error
9554

9655

9756
sys.setrecursionlimit(4096)
@@ -267,15 +226,41 @@ def inference(
267226
tokenizer=tokenizer,
268227
runtime_tokenizer_path=runtime_tokenizer_path,
269228
)
270-
sqnr = sqnr_evaluator.run(prompt=prompt)
271-
logging.info(f"SQNR Eval Score: {sqnr}")
229+
sqnr, golden_logits, _ = sqnr_evaluator.run(prompt=prompt)
230+
logging.info(f"SQNR Eval Score between FP32 nn.Module and QNN: {sqnr}")
272231
eval_results.update(
273232
{
274233
"sqnr": sqnr,
275234
"inference_speed": sqnr_evaluator.inference_speed,
276235
}
277236
)
278237

238+
qdq_ep_path = (
239+
f"{args.pre_gen_pte}/{DECODE_QDQ_FILENAME}"
240+
if args.pre_gen_pte
241+
else f"{args.artifact}/{DECODE_QDQ_FILENAME}"
242+
)
243+
if os.path.exists(qdq_ep_path):
244+
qdq_ep = torch.export.load(qdq_ep_path)
245+
qdq_sqnr_evaluator = SqnrEval(
246+
source_model=qdq_ep.module(),
247+
example_input=source_model.get_example_inputs(),
248+
args=args,
249+
pte_path=pte_path,
250+
tokenizer=tokenizer,
251+
runtime_tokenizer_path=runtime_tokenizer_path,
252+
)
253+
qdq_sqnr, cpu_qdq_logits, _ = qdq_sqnr_evaluator.run(prompt=prompt)
254+
eval_results["qdq_sqnr"] = qdq_sqnr
255+
logging.info(f"SQNR Eval Score between CPU QDQ and QNN: {qdq_sqnr}")
256+
logging.info(
257+
f"SQNR Eval Score between FP32 nn.Module and CPU QDQ: {compute_error(golden_logits, cpu_qdq_logits).item()}"
258+
)
259+
else:
260+
logging.info(
261+
f"Couldn't find saved qdq_ep under {qdq_ep_path}, skip eval sqnr for CPU QDQ."
262+
)
263+
279264
if TASKS_EVAL in args.eval_methods:
280265
# Generate the eval wrapper
281266
ppl_evaluator = TaskEval(

‎examples/qualcomm/oss_scripts/llama/wrappers.py‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
)
5252
from executorch.examples.qualcomm.oss_scripts.llama.decoder_constants import (
5353
AUDIO_ENCODER,
54+
DECODE_QDQ_FILENAME,
5455
DECODER_GRAPH_NAMES,
5556
TEXT_DECODER,
5657
TEXT_EMBEDDING,
@@ -717,8 +718,17 @@ def quantize(self, request: Request): # noqa: C901
717718
tok_embedding=self.tok_embedding,
718719
intermediate_outputs=image_embedding,
719720
)
720-
721721
self.decoder = convert_pt2e(self.decoder)
722+
723+
# Saving Decode QDQ Model EP for SQNR evaluation
724+
if self.mode == self.Mode.DECODE:
725+
qdq_ep = torch.export.export(
726+
self.decoder, self.export_input, strict=True
727+
)
728+
qdq_ep_path = f"{self.control_args.artifact}/{DECODE_QDQ_FILENAME}"
729+
torch.export.save(qdq_ep, qdq_ep_path)
730+
logging.info(f"QDQ EP saved to {qdq_ep_path}")
731+
722732
if self.apply_embedding:
723733
self.tok_embedding = convert_pt2e(self.tok_embedding)
724734

0 commit comments

Comments
 (0)