11
11
selection and combine multiple backends optimally for target hardware.
12
12
"""
13
13
14
- import sys
14
+ import os
15
15
from typing import Dict , List
16
16
17
- if sys .platform != "win32" :
18
- import coremltools as ct
19
- from executorch .backends .apple .coreml .recipes import CoreMLRecipeType
20
-
21
- # pyre-ignore
22
17
from executorch .backends .xnnpack .recipes import XNNPackRecipeType
23
18
from executorch .export .recipe import ExportRecipe , RecipeType
24
-
25
-
26
- ## IOS Target configs
27
- # The following list of recipes are not exhaustive for CoreML; refer to CoreMLRecipeType for more detailed recipes.
28
- IOS_CONFIGS : Dict [str , List [RecipeType ]] = (
29
- {
30
- # pyre-ignore
31
- "ios-arm64-coreml-fp32" : [CoreMLRecipeType .FP32 , XNNPackRecipeType .FP32 ],
32
- # pyre-ignore
33
- "ios-arm64-coreml-fp16" : [CoreMLRecipeType .FP16 ],
34
- # pyre-ignore
35
- "ios-arm64-coreml-int8" : [CoreMLRecipeType .PT2E_INT8_STATIC ],
36
- }
37
- if sys .platform != "win32"
38
- else {}
19
+ from executorch .export .utils import (
20
+ is_supported_platform_for_coreml_lowering ,
21
+ is_supported_platform_for_qnn_lowering ,
39
22
)
40
23
41
24
@@ -46,7 +29,7 @@ def _create_target_recipe(
46
29
Create a combined recipe for a target.
47
30
48
31
Args:
49
- target : Human-readable hardware configuration name
32
+ target_config : Human-readable hardware configuration name
50
33
recipes: List of backend recipe types to combine
51
34
**kwargs: Additional parameters - each backend will use what it needs
52
35
@@ -67,7 +50,6 @@ def _create_target_recipe(
67
50
f"Failed to create { recipe_type .value } recipe for { target_config } : { e } "
68
51
) from e
69
52
70
- # Combine into single recipe
71
53
if len (backend_recipes ) == 1 :
72
54
return backend_recipes [0 ]
73
55
@@ -100,8 +82,24 @@ def get_ios_recipe(
100
82
recipe = get_ios_recipe('ios-arm64-coreml-int8')
101
83
session = export(model, recipe, example_inputs)
102
84
"""
103
- if target_config not in IOS_CONFIGS :
104
- supported = list (IOS_CONFIGS .keys ())
85
+
86
+ if not is_supported_platform_for_coreml_lowering ():
87
+ raise ValueError ("CoreML is not supported on this platform" )
88
+
89
+ import coremltools as ct
90
+ from executorch .backends .apple .coreml .recipes import CoreMLRecipeType
91
+
92
+ ios_configs : Dict [str , List [RecipeType ]] = {
93
+ # pyre-ignore
94
+ "ios-arm64-coreml-fp32" : [CoreMLRecipeType .FP32 , XNNPackRecipeType .FP32 ],
95
+ # pyre-ignore
96
+ "ios-arm64-coreml-fp16" : [CoreMLRecipeType .FP16 ],
97
+ # pyre-ignore
98
+ "ios-arm64-coreml-int8" : [CoreMLRecipeType .PT2E_INT8_STATIC ],
99
+ }
100
+
101
+ if target_config not in ios_configs :
102
+ supported = list (ios_configs .keys ())
105
103
raise ValueError (
106
104
f"Unsupported iOS configuration: '{ target_config } '. "
107
105
f"Supported: { supported } "
@@ -113,5 +111,75 @@ def get_ios_recipe(
113
111
if "minimum_deployment_target" not in kwargs :
114
112
kwargs ["minimum_deployment_target" ] = ct .target .iOS17
115
113
116
- backend_recipes = IOS_CONFIGS [target_config ]
114
+ backend_recipes = ios_configs [target_config ]
115
+ return _create_target_recipe (target_config , backend_recipes , ** kwargs )
116
+
117
+
118
+ # Android Recipe
119
+ def get_android_recipe (
120
+ target_config : str = "android-arm64-snapdragon-fp16" , ** kwargs
121
+ ) -> ExportRecipe :
122
+ """
123
+ Get Android-optimized recipe for specified hardware configuration.
124
+
125
+ Supported configurations:
126
+ - 'android-arm64-snapdragon-fp16': QNN fp16 recipe
127
+
128
+ Args:
129
+ target_config: Android configuration string
130
+ **kwargs: Additional parameters for backend recipes
131
+
132
+ Returns:
133
+ ExportRecipe configured for Android deployment
134
+
135
+ Raises:
136
+ ValueError: If target configuration is not supported
137
+
138
+ Example:
139
+ recipe = get_android_recipe('android-arm64-snapdragon-fp16')
140
+ session = export(model, recipe, example_inputs)
141
+ """
142
+
143
+ if not is_supported_platform_for_qnn_lowering ():
144
+ raise ValueError (
145
+ "QNN is not supported or not properly configured on this platform"
146
+ )
147
+
148
+ try :
149
+ # Qualcomm QNN backend runs QNN sdk download on first use
150
+ # with a pip install, so wrap it in a try/except
151
+ # pyre-ignore
152
+ from executorch .backends .qualcomm .recipes import QNNRecipeType
153
+
154
+ # (1) if this is called from a pip install, the QNN SDK will be available
155
+ # (2) if this is called from a source build, check if qnn is available otherwise, had to run build.sh
156
+ if os .getenv ("QNN_SDK_ROOT" , None ) is None :
157
+ raise ValueError (
158
+ "QNN SDK not found, cannot use QNN recipes. First run `./backends/qualcomm/scripts/build.sh`, if building from source"
159
+ )
160
+ except Exception as e :
161
+ raise ValueError (
162
+ "QNN backend is not available. Please ensure the Qualcomm backend "
163
+ "is properly installed and configured, "
164
+ ) from e
165
+
166
+ android_configs : Dict [str , List [RecipeType ]] = {
167
+ # pyre-ignore
168
+ "android-arm64-snapdragon-fp16" : [QNNRecipeType .FP16 ],
169
+ }
170
+
171
+ if target_config not in android_configs :
172
+ supported = list (android_configs .keys ())
173
+ raise ValueError (
174
+ f"Unsupported Android configuration: '{ target_config } '. "
175
+ f"Supported: { supported } "
176
+ )
177
+
178
+ kwargs = kwargs or {}
179
+
180
+ if target_config == "android-arm64-snapdragon-fp16" :
181
+ if "soc_model" not in kwargs :
182
+ kwargs ["soc_model" ] = "SM8650"
183
+
184
+ backend_recipes = android_configs [target_config ]
117
185
return _create_target_recipe (target_config , backend_recipes , ** kwargs )
0 commit comments