frontend.py Source File

frontend.py Source File#

Mobilint SDK qb Compiler: frontend.py Source File
Mobilint SDK qb Compiler v0.12.0.0
MCS002-KR
frontend.py
Go to the documentation of this file.
1
4
5import pathlib
6from pathlib import Path
7from typing import Any, Optional
8
9import torch
10
11from qubee.compiler.compiler import Compiler
12from qubee.compiler.compiler import _quantization_task
13from qubee.configs import *
14from qubee.version import __version__
15
16
21
22
23class Model_Dict(Compiler):
24 """
25 @brief Wrapper around the Mobilint compiler to support compilation and inference workflows.
26
27 @details Capabilities include:
28 - Compilation of models into MXQ artifacts runnable on Mobilint NPUs.
29 - Inference using the full-precision high-level compiled model on CPU or GPU.
30 - Inference with the quantized model on CPU or GPU.
31 """
32
34 self,
35 model,
36 backend="onnx",
37 device="cpu",
38 feed_dict=None,
39 dynamic_axes=None,
40 in_dformats=None,
41 yolo_decode_include=False,
42 **kwargs,
43 ):
44 """
45 @brief Initialize the Mobilint compiler wrapper.
46
47 @param model string or model instance. Model path or in-memory model to compile.
48 @param backend string. Framework identifier for the model (for example "onnx"). Defaults to "onnx".
49 @param device string. Target device for inference ("cpu" or "gpu"). Defaults to "cpu".
50 @param feed_dict dict. Example inputs for shape resolution.
51 @param dynamic_axes dict. Marks model axes as dynamic.
52 @param in_dformats dict. Describes input data formats.
53 @param yolo_decode_include bool. Runs YOLO decode on NPU when @c True.
54 @param kwargs dict. Additional compiler arguments.
55 """
56 super().__init__(
57 model=model,
58 backend=backend,
59 device=device,
60 feed_dict=feed_dict,
61 in_dformats=in_dformats,
62 dynamic_axes=dynamic_axes,
63 yolo_decode_include=yolo_decode_include,
64 **kwargs,
65 )
66
68 self,
69 calib_data_path: str = None,
70 save_path: str = None,
71 save_subgraph_type: int = 0,
72 output_subgraph_path="",
73 model_nickname: str = None,
74 save_sample=False,
75 use_random_calib=False,
76 inference_scheme="single",
77 cpu_offload=False,
78 singlecore_compile=False,
79 optimize_option=0,
80 sample_dtype: str = "float",
81 preprocess_dict=None,
82 buffer_mode=1,
83 start_dram_offset=0,
84 compile_config=None, # CompileConfig object
85 **kwargs,
86 ):
87 """
88 @brief Compile the wrapped model into an MXQ artifact.
89
90 @param calib_data_path string. Calibration dataset directory or meta file (.txt/.json) listing NumPy samples.
91 @param save_path string. Output MXQ filename.
92 @param save_subgraph_type int. Controls optional MBLT exports: 0 disables; 1 saves graph structure; 2 saves
93 structure and weights; 3 splits structure into multiple subgraphs; 4 splits structure and weights.
94 @param output_subgraph_path string. Destination for exported .mblt when @p save_subgraph_type is 1–4.
95 @param model_nickname string. Friendly name stored in qubee for faster recompile.
96 @param save_sample bool. Persists inputs/outputs for debugging in ./sampleInOut.
97 @param use_random_calib bool. Uses randomly generated calibration samples when @c True.
98 @param inference_scheme string. NPU inference configuration ("single", "multi", "global", etc.).
99 @param cpu_offload bool. Enables CPU offload for unsupported groups.
100 @param singlecore_compile bool. Forces single-core compilation for large DRAM usage.
101 @param optimize_option int. Compiler optimization selector.
102 @param sample_dtype string. Data type used for saved sample outputs.
103 @param preprocess_dict dict. Additional preprocessing metadata.
104 @param buffer_mode int. Buffer serialization mode (0 naive, 1 mmap).
105 @param start_dram_offset int. Start Dram Address Offset (default = 0).
106 @param compile_config CompileConfig. Compile configuration object.
107 @param kwargs dict. Additional arguments forwarded to the compiler.
108
109 """
110 super().compile(
111 calib_data_path=calib_data_path,
112 save_path=save_path,
113 save_subgraph_type=save_subgraph_type,
114 output_subgraph_path=output_subgraph_path,
115 model_nickname=model_nickname,
116 save_sample=save_sample,
117 inference_scheme=inference_scheme,
118 use_random_calib=use_random_calib,
119 cpu_offload=cpu_offload,
120 singlecore_compile=singlecore_compile,
121 optimize_option=optimize_option,
122 sample_dtype=sample_dtype,
123 preprocess_dict=preprocess_dict,
124 buffer_mode=buffer_mode,
125 start_dram_offset=start_dram_offset,
126 compile_config=compile_config,
127 **kwargs,
128 )
129
130
131def mxq_compile(
132 model,
133 calib_data_path: str = "",
134 save_subgraph_type: int = 0,
135 output_subgraph_path="",
136 model_nickname: str = None,
137 save_path: str = None,
138 backend="onnx",
139 device="cpu",
140 feed_dict=None,
141 dynamic_axes=None,
142 in_dformats=None,
143 save_sample=False,
144 inference_scheme="single",
145 yolo_decode_include=False,
146 use_random_calib=False,
147 cpu_offload=False,
148 singlecore_compile=False,
149 optimize_option=0,
150 sample_dtype="float",
151 preprocess_dict=None,
152 buffer_mode=1,
153 start_dram_offset=0,
154 input_shape_dict=dict(),
155 compile_config: Optional[CompileConfig] = None,
156 resource_management_config: Optional[ResourceManagementConfig] = None,
157 quantization_config: Optional[QuantizationConfig] = None,
158 advanced_quantization_config: Optional[AdvancedQuantizationConfig] = None,
159 llm_config: Optional[LlmConfig] = None,
160 **kwargs,
161):
162 """
163 @brief Compile a model into a Mobilint eXeCUtable (MXQ) package for execution on Mobilint NPUs.
164
165 @param model string or model instance. Model path. When using @c backend="onnx", this should be the path to an ONNX
166 model file. When @c backend is "torchscript", provide a TorchScript module; when "torch", provide a standard
167 PyTorch model. For @c backend="tf", pass the directory that contains the TensorFlow SavedModel graph and assets. For
168 @c backend="tflite", pass the TF Lite model path.
169 @param calib_data_path string. Path to the calibration dataset. Accepts either a text/json file that lists NumPy
170 files or a directory that contains the pre-processed NumPy files.
171 @param save_subgraph_type int. Controls optional MBLT subgraph exports: 0 disables exports; 1 saves only the graph
172 structure; 2 saves graph structure plus weights; 3 saves the graph structure split into multiple subgraphs; 4 saves
173 both structure and weights split into multiple subgraphs.
174 @param output_subgraph_path string. Destination path for the exported .mblt file when @p save_subgraph_type is 1, 2,
175 3, or 4. The resulting file can be used for visualization.
176 @param model_nickname string. Friendly name stored in qubee. Defaults to the model basename (for example, the file
177 "/workspace/onnx/resnet50.onnx" becomes "resnet50"). Falls back to "temporary" when it cannot be inferred.
178 @param save_path string. Output MXQ filename. Defaults to "{model_nickname}.mxq" when omitted.
179 @param backend string. Framework used to generate the Mobilint IR. Must be one of "onnx", "tf", "tflite",
180 "torchscript", or "torch". Defaults to "onnx".
181 @param device string. Compilation and inference device: "cpu" or "gpu". Defaults to "cpu".
182 @param feed_dict dict. Example input tensors for shape inference and inference validation.
183 @param dynamic_axes dict. Marks model axes as dynamic. Keys are input names and values map dimension indices to
184 aliases (for example {"input": {2: "seq_len"}}).
185 @param in_dformats dict. Describes input tensor data formats.
186 @param save_sample bool. Stores input/output tensors in ./sampleInOut when @c True to aid debugging. Defaults to
187 @c False.
188 @param inference_scheme string. NPU inference scheme. One of "single", "multi", "global", "global4", or
189 "global8".
190 @param yolo_decode_include bool. Determines whether YOLO decode runs on NPU.
191 @param use_random_calib bool. Generates random calibration data to validate model compilability. Defaults to @c
192 False.
193 @param cpu_offload bool. Enables CPU offloading during NPU inference. Defaults to @c False.
194 @param singlecore_compile bool. Uses singlecore compilation to maximize DRAM usage. Defaults to @c False.
195 @param optimize_option int. Compiler optimization strategy selector.
196 @param sample_dtype string. Data type for saved sample inference outputs: "float" or "int8".
197 @param preprocess_dict int. Identifier for additional pre-processing metadata.
198 @param buffer_mode int. Buffer serialization mode: 0 uses a naïve buffer, 1 uses an mmap-backed buffer. Defaults to
199 1.
200 @param start_dram_offset int. Start Dram Address Offset (default = 0).
201 @param input_shape_dict dict. Optional HWC input shape dictionary used for multi-shape compilation (for example
202 {"input0": [[224, 224, 3], [256, 256, 3]]}).
203 @param compile_config string. Path to JSON configuration file containing all quantization-related settings
204 (resourceManagement, quantization, advancedQuantization, llmConfig). If provided, this takes precedence over
205 individual sub-config parameters.
206 @param resource_management_config ResourceManagementConfig. Resource management configuration object.
207 @param quantization_config QuantizationConfig. Quantization configuration object.
208 @param advanced_quantization_config AdvancedQuantizationConfig. Advanced quantization configuration object.
209 @param llm_config LlmConfig. LLM configuration object.
210 @param kwargs dict. Additional compiler arguments propagated to the backend implementation. Moreover, If you want to override only
211 a subset of configuration values, you can pass them to `mxq_compile` as keyword arguments (`kwargs`), and they will be applied.
212 Note that `AdvancedQuantizationConfig` and its sub-configurations are not updated automatically from `kwargs`. In contrast, `ResourceManagementConfig`,
213 `QuantizationConfig`, and `LlmConfig` support automatic updates via each configuration class’s `from_kwargs` method. See Example 3 below for a usage example.
214 @return None.
215
216 @par Using configuration
217 There are two ways to configure quantization settings:
218
219 1. Load all settings from a JSON config file:
220 @code{.py}
221 from qubee import mxq_compile
222
223 mxq_compile(
224 model="path/to/model.onnx",
225 calib_data_path="path/to/calib",
226 compile_config="path/to/config.json",
227 device="gpu",
228 )
229 @endcode
230
231 2. Pass individual sub-config objects:
232 @code{.py}
233 from qubee import mxq_compile
234 from qubee.configs import (
235 ResourceManagementConfig,
236 QuantizationConfig,
237 AdvancedQuantizationConfig,
238 LlmConfig,
239 )
240
241 resource_mgmt = ResourceManagementConfig(weight_dtype="float32")
242 quant_cfg = QuantizationConfig(...)
243 adv_quant_cfg = AdvancedQuantizationConfig(...)
244 llm_cfg = LlmConfig(...)
245
246 mxq_compile(
247 model="path/to/model.onnx",
248 calib_data_path="path/to/calib",
249 resource_management_config=resource_mgmt,
250 quantization_config=quant_cfg,
251 advanced_quantization_config=adv_quant_cfg,
252 llm_config=llm_cfg,
253 device="gpu",
254 )
255 @endcode
256
257 3. Automatically applied partial configuration overrides:
258 @code{.py}
259 from qubee import mxq_compile
260
261 mxq_compile(
262 model="path/to/model.onnx",
263 calib_data_path="path/to/calib",
264 quantization_method=1, # per channel quantization
265 quantization_mode=2, # max percentile quantization
266 percentile=0.999, # percentile value for max percentile quantization
267 quantization_output=0, # per layer quantization for the output layer
268 device="gpu",
269 )
270 @endcode
271 Please refer to the mxq_compile function and the quantization configuration section for the meaning of the quantization-related numeric values.
272
273 @par Compiling models with custom inputs (ONNX/Torch/TensorFlow)
274 Provide NumPy inputs whenever the model omits shape information so that qubee can infer unknown dimensions and data
275 formats.
276
277 @code{.py}
278 from qubee import mxq_compile
279 import numpy as np
280
281 example_input = {
282 "input_node_name_1": np.random.randn(1, 3, 224, 224).astype(np.float32),
283 "input_node_name_2": np.random.randn(1, 8, 224, 224).astype(np.float32),
284 "input_node_name_3": np.random.randn(1, 4, 56, 56).astype(np.float32),
285 }
286
287 in_dformats = {
288 "input_node_name_1": "NCHW",
289 "input_node_name_2": "NCHW",
290 "input_node_name_3": "NCHW",
291 }
292
293 onnx_model_path = "path/to/your/model.onnx"
294 mxq_compile(
295 model=onnx_model_path,
296 feed_dict=example_input,
297 in_dformats=in_dformats,
298 backend="onnx",
299 compile_config="path/to/config.json",
300 )
301 @endcode
302 """
303 if model_nickname and isinstance(model_nickname, str):
304 model_name = model_nickname
305 elif isinstance(model, str): # in the case of model path
306 model_name = Path(model).stem
307 else: # in the case of model instance
308 if save_path is None:
309 raise ValueError("Please set the save_path with .mxq extension")
310 model_name = "model"
311 if save_path is None:
312 save_path = f"{model_name}.mxq"
313
314 # Handle config loading
315 if compile_config is not None:
316 # Accept both CompileConfig object and JSON file path
317 if isinstance(compile_config, CompileConfig):
318 compile_cfg = compile_config
319 elif isinstance(compile_config, str):
320 compile_cfg = CompileConfig.from_json(
321 compile_config,
322 calib_data_path=calib_data_path,
323 use_random_calib=use_random_calib,
324 save_path=save_path,
325 save_msgpack_name=None,
326 model_nickname=model_name,
327 model_path=None,
328 inference_scheme=inference_scheme,
329 save_sample=save_sample,
330 cpu_offload=cpu_offload,
331 singlecore_compile=singlecore_compile,
332 optimize_option=optimize_option,
333 sample_dtype=sample_dtype,
334 preprocess_dict=preprocess_dict,
335 buffer_mode=buffer_mode,
336 start_dram_offset=start_dram_offset,
337 version=__version__,
338 input_shape_dict=input_shape_dict,
339 )
340 else:
341 raise ValueError(
342 "compile_config must be either a CompileConfig object or a path to JSON configuration file"
343 )
344 else:
345 pairs = [
346 (
347 "resource_management_config",
348 resource_management_config,
349 ResourceManagementConfig,
350 ),
351 ("quantization_config", quantization_config, QuantizationConfig),
352 (
353 "advanced_quantization_config",
354 advanced_quantization_config,
355 AdvancedQuantizationConfig,
356 ),
357 ("llm_config", llm_config, LlmConfig),
358 ]
359 for name, obj, expected_cls in pairs:
360 if obj is None:
361 continue
362 if not isinstance(obj, expected_cls):
363 raise TypeError(
364 f"Invalid type for '{name}': expected {expected_cls.__name__} or None, "
365 f"but got {type(obj).__name__}."
366 )
367
368 compile_cfg = get_compile_config(
369 calib_data_path=calib_data_path,
370 use_random_calib=use_random_calib,
371 save_path=save_path,
372 save_msgpack_name=None,
373 model_nickname=model_name,
374 model_path=None,
375 inference_scheme=inference_scheme,
376 save_sample=save_sample,
377 cpu_offload=cpu_offload,
378 singlecore_compile=singlecore_compile,
379 optimize_option=optimize_option,
380 sample_dtype=sample_dtype,
381 preprocess_dict=preprocess_dict,
382 buffer_mode=buffer_mode,
383 start_dram_offset=start_dram_offset,
384 version=__version__,
385 input_shape_dict=input_shape_dict,
386 resource_management_config=resource_management_config,
387 quantization_config=quantization_config,
388 llm_config=llm_config,
389 advanced_quantization_config=advanced_quantization_config, # AdvancedQuantizationConfig config don't use "from_kwargs" because of shared key names, such as "apply".
390 **kwargs,
391 )
392
393 if isinstance(model, str) and model.endswith(".mblt") and os.path.isfile(model):
394 _quantization_task(model, device, compile_config=compile_cfg)
395 else:
396 model_dict = Model_Dict(
397 model=model,
398 backend=backend,
399 device=device,
400 feed_dict=feed_dict,
401 in_dformats=in_dformats,
402 dynamic_axes=dynamic_axes,
403 yolo_decode_include=yolo_decode_include,
404 **kwargs,
405 )
406 model_dict.compile(
407 model_nickname=model_name,
408 calib_data_path=calib_data_path,
409 save_path=save_path,
410 save_subgraph_type=save_subgraph_type,
411 output_subgraph_path=output_subgraph_path,
412 save_sample=save_sample,
413 inference_scheme=inference_scheme,
414 use_random_calib=use_random_calib,
415 cpu_offload=cpu_offload,
416 singlecore_compile=singlecore_compile,
417 optimize_option=optimize_option,
418 sample_dtype=sample_dtype,
419 preprocess_dict=preprocess_dict,
420 buffer_mode=buffer_mode,
421 start_dram_offset=start_dram_offset,
422 compile_config=compile_cfg,
423 )
424 torch.cuda.empty_cache()
425 del model_dict
426
427
428
430
431
432def mblt_compile(
433 model: str | Any,
434 mblt_save_path: str,
435 backend="onnx",
436 device="cpu",
437 feed_dict=None,
438 dynamic_axes=None,
439 in_dformats=None,
440 yolo_decode_include=False,
441 cpu_offload=False,
442 **kwargs,
443):
444 """
445 @brief Export a model to the Mobilint .mblt format without producing an MXQ package.
446
447 @param model string or model instance. Source model or path to compile.
448 @param mblt_save_path string. Output path for the .mblt artifact.
449 @param backend string. Framework identifier ("onnx", "tf", "tflite", "torchscript", or "torch"). Defaults to
450 "onnx".
451 @param device string. Compilation device ("cpu" or "gpu"). Defaults to "cpu".
452 @param feed_dict dict. Example inputs used for shape inference.
453 @param dynamic_axes dict. Declares dynamic axes per input name.
454 @param in_dformats dict. Input dataformat metadata.
455 @param yolo_decode_include bool. Runs YOLO decode on NPU when True.
456 @param cpu_offload bool. Enables CPU offloading for unsupported groups.
457 @param kwargs dict. Additional arguments forwarded to the compiler.
458 @return None.
459 """
460 model_dict = Model_Dict(
461 model=model,
462 backend=backend,
463 device=device,
464 feed_dict=feed_dict,
465 dynamic_axes=dynamic_axes,
466 in_dformats=in_dformats,
467 yolo_decode_include=yolo_decode_include,
468 **kwargs,
469 )
470
471 model_dict.mblt_compile(
472 model,
473 mblt_save_path=mblt_save_path,
474 backend=backend,
475 cpu_offload=cpu_offload,
476 **kwargs,
477 )
478
479
480def run_mblt_model(
481 path_to_mblt: str,
482 save_all_outputs: bool = True,
483 inference_output_path: Optional[str] = None,
484 target_subgraph: Optional[int] = None,
485):
486 from qubee.model_dict.common.model_dict import ValueDict
487 from qubee.model_dict.inference.model import ModelInference
488 from qubee.model_dict.serialize import load_mblt_model
489
490 assert path_to_mblt.endswith(".mblt")
491 if not save_all_outputs:
492 raise NotImplementedError(
493 f"save_all_outputs={save_all_outputs} is not supported yet."
494 )
495 if target_subgraph:
496 raise NotImplementedError(
497 f"target_subgraph={target_subgraph} is not supported yet."
498 )
499 import numpy
500
501 if not inference_output_path:
502 inference_output_path = str(pathlib.Path(path_to_mblt).with_suffix(".infer"))
503
504 vd = ValueDict()
505 md, wd = load_mblt_model(path_to_mblt, load_weight=True)
506 for sg in md.subgraphs:
507 for iidx in sg.inputs:
508 inact = sg.activations[iidx]
509 if inact.name in set(md.inputs):
510 vd[inact.name] = numpy.random.random(tuple(map(int, inact.src_shape)))
511
512 model_inference = ModelInference(
513 model_dict=md,
514 weight_dict=wd,
515 value_dict=vd,
516 save_all_outputs=save_all_outputs,
517 inference_all_outputs_write_path=inference_output_path,
518 )
519
520 model_inference.run_inference(use_value_dict_data_for_next_input=False)
Wrapper around the Mobilint compiler to support compilation and inference workflows.
Definition frontend.py:23
compile(self, str calib_data_path=None, str save_path=None, int save_subgraph_type=0, output_subgraph_path="", str model_nickname=None, save_sample=False, use_random_calib=False, inference_scheme="single", cpu_offload=False, singlecore_compile=False, optimize_option=0, str sample_dtype="float", preprocess_dict=None, buffer_mode=1, start_dram_offset=0, compile_config=None, **kwargs)
Compile the wrapped model into an MXQ artifact.
Definition frontend.py:86
__init__(self, model, backend="onnx", device="cpu", feed_dict=None, dynamic_axes=None, in_dformats=None, yolo_decode_include=False, **kwargs)
Initialize the Mobilint compiler wrapper.
Definition frontend.py:43
mxq_compile(model, str calib_data_path="", int save_subgraph_type=0, output_subgraph_path="", str model_nickname=None, str save_path=None, backend="onnx", device="cpu", feed_dict=None, dynamic_axes=None, in_dformats=None, save_sample=False, inference_scheme="single", yolo_decode_include=False, use_random_calib=False, cpu_offload=False, singlecore_compile=False, optimize_option=0, sample_dtype="float", preprocess_dict=None, buffer_mode=1, start_dram_offset=0, input_shape_dict=dict(), Optional[CompileConfig] compile_config=None, Optional[ResourceManagementConfig] resource_management_config=None, Optional[QuantizationConfig] quantization_config=None, Optional[AdvancedQuantizationConfig] advanced_quantization_config=None, Optional[LlmConfig] llm_config=None, **kwargs)
Compile a model into a Mobilint eXeCUtable (MXQ) package for execution on Mobilint NPUs.
Definition frontend.py:161
mblt_compile(str|Any model, str mblt_save_path, backend="onnx", device="cpu", feed_dict=None, dynamic_axes=None, in_dformats=None, yolo_decode_include=False, cpu_offload=False, **kwargs)
Export a model to the Mobilint .mblt format without producing an MXQ package.
Definition frontend.py:443