Skip to content

Commit c4d068d

Browse files
Add android target recipes and extensive model tests using ios and android recipes
Summary: Changes in this diff: 1. Adds android target recipes using QNN backend. 2. Add extensive model lowering and accuracy checks using torchvision models. ``` from executorch.export import export qnn_android_recipe = get_android_recipe() # lower a model to pte session = export(model, recipe, example_inputs) out = session.run_method("forward", *example_inputs) ``` Differential Revision: D82284987
1 parent 10e93fb commit c4d068d

File tree

6 files changed

+619
-77
lines changed

6 files changed

+619
-77
lines changed

backends/qualcomm/_passes/TARGETS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ runtime.python_library(
1515
"//executorch/backends/transforms:decompose_sdpa",
1616
"//executorch/exir/backend:backend_details",
1717
"//executorch/exir/backend:compile_spec_schema",
18+
"//executorch/backends/qualcomm/quantizer:quantizer",
1819
],
1920
)

export/TARGETS

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,19 @@ runtime.python_library(
117117
"target_recipes.py",
118118
],
119119
deps = [
120+
":export_utils",
120121
"fbsource//third-party/pypi/coremltools:coremltools",
121122
"//executorch/export:recipe",
122123
"//executorch/backends/xnnpack/recipes:xnnpack_recipes",
123124
"//executorch/backends/apple/coreml:coreml_recipes",
125+
"//executorch/backends/qualcomm/recipes:qnn_recipes",
126+
]
127+
)
128+
129+
runtime.python_library(
130+
name = "export_utils",
131+
srcs = ["utils.py"],
132+
deps = [
133+
"//caffe2:torch",
124134
]
125135
)

export/target_recipes.py

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,40 @@
1717

1818
# pyre-ignore
1919
from executorch.backends.apple.coreml.recipes import CoreMLRecipeType
20+
21+
# pyre-ignore
22+
from executorch.backends.qualcomm.recipes import QNNRecipeType
2023
from executorch.backends.xnnpack.recipes import XNNPackRecipeType
2124
from executorch.export.recipe import ExportRecipe, RecipeType
22-
25+
from executorch.export.utils import (
26+
is_supported_platform_for_coreml_lowering,
27+
is_supported_platform_for_qnn_lowering,
28+
)
2329

2430
## IOS Target configs
2531
# The following list of recipes are not exhaustive for CoreML; refer to CoreMLRecipeType for more detailed recipes.
26-
IOS_CONFIGS: Dict[str, List[RecipeType]] = {
27-
# pyre-ignore
28-
"ios-arm64-coreml-fp32": [CoreMLRecipeType.FP32, XNNPackRecipeType.FP32],
29-
# pyre-ignore
30-
"ios-arm64-coreml-fp16": [CoreMLRecipeType.FP16],
31-
# pyre-ignore
32-
"ios-arm64-coreml-int8": [CoreMLRecipeType.PT2E_INT8_STATIC],
33-
}
32+
IOS_CONFIGS: Dict[str, List[RecipeType]] = (
33+
{
34+
# pyre-ignore
35+
"ios-arm64-coreml-fp32": [CoreMLRecipeType.FP32, XNNPackRecipeType.FP32],
36+
# pyre-ignore
37+
"ios-arm64-coreml-fp16": [CoreMLRecipeType.FP16],
38+
# pyre-ignore
39+
"ios-arm64-coreml-int8": [CoreMLRecipeType.PT2E_INT8_STATIC],
40+
}
41+
if is_supported_platform_for_coreml_lowering()
42+
else {}
43+
)
44+
45+
# Android Target configs
46+
ANDROID_CONFIGS: Dict[str, List[RecipeType]] = (
47+
{
48+
# pyre-ignore
49+
"android-arm64-snapdragon-fp16": [QNNRecipeType.FP16],
50+
}
51+
if is_supported_platform_for_qnn_lowering()
52+
else {}
53+
)
3454

3555

3656
def _create_target_recipe(
@@ -40,7 +60,7 @@ def _create_target_recipe(
4060
Create a combined recipe for a target.
4161
4262
Args:
43-
target: Human-readable hardware configuration name
63+
target_config: Human-readable hardware configuration name
4464
recipes: List of backend recipe types to combine
4565
**kwargs: Additional parameters - each backend will use what it needs
4666
@@ -61,7 +81,6 @@ def _create_target_recipe(
6181
f"Failed to create {recipe_type.value} recipe for {target_config}: {e}"
6282
) from e
6383

64-
# Combine into single recipe
6584
if len(backend_recipes) == 1:
6685
return backend_recipes[0]
6786

@@ -94,6 +113,10 @@ def get_ios_recipe(
94113
recipe = get_ios_recipe('ios-arm64-coreml-int8')
95114
session = export(model, recipe, example_inputs)
96115
"""
116+
117+
if not is_supported_platform_for_coreml_lowering():
118+
raise ValueError("CoreML is not supported on this platform")
119+
97120
if target_config not in IOS_CONFIGS:
98121
supported = list(IOS_CONFIGS.keys())
99122
raise ValueError(
@@ -109,3 +132,48 @@ def get_ios_recipe(
109132

110133
backend_recipes = IOS_CONFIGS[target_config]
111134
return _create_target_recipe(target_config, backend_recipes, **kwargs)
135+
136+
137+
# Android Recipe
138+
def get_android_recipe(
139+
target_config: str = "android-arm64-snapdragon-fp16", **kwargs
140+
) -> ExportRecipe:
141+
"""
142+
Get Android-optimized recipe for specified hardware configuration.
143+
144+
Supported configurations:
145+
- 'android-arm64-snapdragon-fp16': QNN fp16 recipe
146+
147+
Args:
148+
target_config: Android configuration string
149+
**kwargs: Additional parameters for backend recipes
150+
151+
Returns:
152+
ExportRecipe configured for Android deployment
153+
154+
Raises:
155+
ValueError: If target configuration is not supported
156+
157+
Example:
158+
recipe = get_android_recipe('android-arm64-snapdragon-fp16')
159+
session = export(model, recipe, example_inputs)
160+
"""
161+
162+
if not is_supported_platform_for_qnn_lowering():
163+
raise ValueError("QNN is not supported on this platform")
164+
165+
if target_config not in ANDROID_CONFIGS:
166+
supported = list(ANDROID_CONFIGS.keys())
167+
raise ValueError(
168+
f"Unsupported Android configuration: '{target_config}'. "
169+
f"Supported: {supported}"
170+
)
171+
172+
kwargs = kwargs or {}
173+
174+
if target_config == "android-arm64-snapdragon-fp16":
175+
if "soc_model" not in kwargs:
176+
kwargs["soc_model"] = "SM8650"
177+
178+
backend_recipes = ANDROID_CONFIGS[target_config]
179+
return _create_target_recipe(target_config, backend_recipes, **kwargs)

export/tests/TARGETS

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
load("@fbsource//xplat/executorch/build:runtime_wrapper.bzl", "runtime")
2+
load("@fbsource//xplat/executorch/backends/qualcomm/qnn_version.bzl", "get_qnn_library_version")
23

34
oncall("executorch")
45

@@ -37,11 +38,23 @@ runtime.python_test(
3738
srcs = [
3839
"test_target_recipes.py",
3940
],
41+
env = {
42+
"LD_LIBRARY_PATH": "$(location fbsource//third-party/qualcomm/qnn/qnn-{0}:qnn_offline_compile_libs)".format(get_qnn_library_version()),
43+
"QNN_SDK_ROOT": "$(location fbsource//third-party/qualcomm/qnn/qnn-{0}:__dir__)".format(get_qnn_library_version()),
44+
"HTTP_PROXY": "http://fwdproxy:8080",
45+
"HTTPS_PROXY": "http://fwdproxy:8080",
46+
},
47+
labels = ["long_running"],
4048
deps = [
4149
"//executorch/export:lib",
4250
"//executorch/export:target_recipes",
51+
"//executorch/export:export_utils",
4352
"//executorch/runtime:runtime",
4453
"//executorch/backends/xnnpack/recipes:xnnpack_recipes",
4554
"//executorch/backends/apple/coreml:coreml_recipes",
55+
"//executorch/backends/qualcomm/recipes:qnn_recipes",
56+
"//executorch/examples/models:models",
57+
"//executorch/backends/xnnpack/test/tester:tester",
58+
"fbsource//third-party/pypi/coremltools:coremltools"
4659
]
4760
)

0 commit comments

Comments
 (0)