3
3
# CoreML backend for delegating a EdgeProgram to CoreML.
4
4
5
5
import json
6
+ import logging
6
7
7
8
import shutil
8
9
import uuid
14
15
from typing import Any , Dict , final , List , Optional , Tuple
15
16
16
17
import coremltools as ct
18
+ import coremltools .optimize as cto
17
19
import executorchcoreml
18
20
19
21
from executorch .exir .backend .backend_details import (
23
25
)
24
26
from executorch .exir .backend .compile_spec_schema import CompileSpec
25
27
28
+ logger = logging .getLogger (__name__ )
29
+ logger .setLevel (logging .WARNING )
30
+
26
31
27
32
class COMPILE_SPEC_KEYS (Enum ):
28
33
COMPUTE_UNITS = "compute_units"
29
34
MODEL_TYPE = "model_type"
30
35
MIN_DEPLOYMENT_TARGET = "min_deployment_target"
31
36
MODEL_COMPUTE_PRECISION = "model_compute_precision"
37
+ OP_LINEAR_QUANTIZER_CONFIG = "op_linear_quantizer_config"
32
38
33
39
34
40
class MODEL_PATHS (Enum ):
@@ -169,12 +175,39 @@ def generate_compute_unit_compile_spec(
169
175
compute_unit .name .lower ().encode ("utf-8" ),
170
176
)
171
177
178
+ @staticmethod
179
+ def generate_op_linear_quantizer_config_compile_spec (
180
+ op_linear_quantizer_config : str ,
181
+ ) -> CompileSpec :
182
+ """
183
+ Returns the compile spec representing the model post conversion quantization,
184
+ which is a dict str that will construct cto.coreml.OpLinearQuantizerConfig
185
+ """
186
+ return CompileSpec (
187
+ COMPILE_SPEC_KEYS .OP_LINEAR_QUANTIZER_CONFIG .value ,
188
+ op_linear_quantizer_config .encode ("utf-8" ),
189
+ )
190
+
191
+ @staticmethod
192
+ def op_linear_quantizer_config_from_compile_specs (
193
+ compile_specs : List [CompileSpec ],
194
+ ) -> Dict :
195
+ """
196
+ Returns the model's post conversion quantization by parsing the list of compile specs.
197
+ """
198
+ for compile_spec in compile_specs :
199
+ if compile_spec .key == COMPILE_SPEC_KEYS .OP_LINEAR_QUANTIZER_CONFIG .value :
200
+ return compile_spec .value .decode ("utf-8" )
201
+
202
+ return None
203
+
172
204
@staticmethod
173
205
def generate_compile_specs (
174
206
compute_unit : ct .ComputeUnit = ct .ComputeUnit .ALL ,
175
207
minimum_deployment_target : ct .target = ct .target .iOS15 ,
176
208
compute_precision : ct .precision = ct .precision .FLOAT16 ,
177
209
model_type : MODEL_TYPE = MODEL_TYPE .MODEL ,
210
+ op_linear_quantizer_config : Optional [str ] = None ,
178
211
) -> List [CompileSpec ]:
179
212
"""
180
213
Returns the list of compile specs that's used by CoreMLBackend to lower the module.
@@ -192,6 +225,12 @@ def generate_compile_specs(
192
225
CoreMLBackend .generate_compute_precision_compile_spec (compute_precision )
193
226
)
194
227
compile_specs .append (CoreMLBackend .generate_model_type_compile_spec (model_type ))
228
+ if op_linear_quantizer_config is not None :
229
+ compile_specs .append (
230
+ CoreMLBackend .generate_op_linear_quantizer_config_compile_spec (
231
+ op_linear_quantizer_config
232
+ )
233
+ )
195
234
196
235
return compile_specs
197
236
@@ -368,18 +407,18 @@ def preprocess(
368
407
compile_specs ,
369
408
)
370
409
)
371
-
372
410
model_compute_precision : ct .precision = (
373
411
CoreMLBackend .model_compute_precision_from_compile_specs (compile_specs )
374
412
)
375
-
376
413
minimum_deployment_target : ct .target = (
377
414
CoreMLBackend .min_deployment_target_from_compile_specs (compile_specs )
378
415
)
379
-
380
416
compute_units : ct .ComputeUnit = CoreMLBackend .compute_unit_from_compile_specs (
381
417
compile_specs
382
418
)
419
+ op_linear_quantizer_config = (
420
+ CoreMLBackend .op_linear_quantizer_config_from_compile_specs (compile_specs )
421
+ )
383
422
384
423
mlmodel = ct .convert (
385
424
model = edge_program ,
@@ -392,4 +431,19 @@ def preprocess(
392
431
compute_units = compute_units ,
393
432
)
394
433
434
+ if op_linear_quantizer_config is not None :
435
+ logger .warning (
436
+ "Core ML Backend op_linear_quantizer_config API is experimental"
437
+ )
438
+ config_dict = json .loads (op_linear_quantizer_config )
439
+ global_op_config = cto .coreml .OpLinearQuantizerConfig ._from_dict (
440
+ config_dict
441
+ )
442
+ config = cto .coreml .OptimizationConfig (
443
+ global_config = global_op_config ,
444
+ # skip embedding
445
+ op_type_configs = {"gather" : None },
446
+ )
447
+ mlmodel = cto .coreml .linear_quantize_weights (mlmodel , config = config )
448
+
395
449
return CoreMLBackend .preprocess_model (mlmodel , model_type = model_type )
0 commit comments