1111selection and combine multiple backends optimally for target hardware.
1212"""
1313
14- import sys
14+ import os
1515from typing import Dict , List
1616
17- if sys .platform != "win32" :
18- import coremltools as ct
19- from executorch .backends .apple .coreml .recipes import CoreMLRecipeType
20-
21- # pyre-ignore
2217from executorch .backends .xnnpack .recipes import XNNPackRecipeType
2318from 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 ,
3922)
4023
4124
@@ -46,7 +29,7 @@ def _create_target_recipe(
4629 Create a combined recipe for a target.
4730
4831 Args:
49- target : Human-readable hardware configuration name
32+ target_config : Human-readable hardware configuration name
5033 recipes: List of backend recipe types to combine
5134 **kwargs: Additional parameters - each backend will use what it needs
5235
@@ -67,7 +50,6 @@ def _create_target_recipe(
6750 f"Failed to create { recipe_type .value } recipe for { target_config } : { e } "
6851 ) from e
6952
70- # Combine into single recipe
7153 if len (backend_recipes ) == 1 :
7254 return backend_recipes [0 ]
7355
@@ -100,8 +82,24 @@ def get_ios_recipe(
10082 recipe = get_ios_recipe('ios-arm64-coreml-int8')
10183 session = export(model, recipe, example_inputs)
10284 """
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 ())
105103 raise ValueError (
106104 f"Unsupported iOS configuration: '{ target_config } '. "
107105 f"Supported: { supported } "
@@ -113,5 +111,75 @@ def get_ios_recipe(
113111 if "minimum_deployment_target" not in kwargs :
114112 kwargs ["minimum_deployment_target" ] = ct .target .iOS17
115113
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 ]
117185 return _create_target_recipe (target_config , backend_recipes , ** kwargs )
0 commit comments