Port a model using Qualcomm Neural Processing Engine SDK
Model conversion
A pretrained floating point, 32-bit precision model from PyTorch, ONNX, TensorFlow, or TFLite is input to SNPE converter tools (snpe-<framework>-to-dlc) to convert the model to a Qualcomm-specific intermediate representation of the model called a deep learning container (DLC).In addition to the input model from a source framework, the converters require additional details about the input model, such as the input node name, its corresponding input dimensions, and any output tensor names (for models with multiple outputs).Refer to converters for all available configurable parameters or see the command line help by running:Output:If the yaml package is not present in your working environment, install it using the following command: The following example uses an ONNX model (inception_v3_opset16.onnx) downloaded from the ONNX Model Zoo.Download the model as inception_v3.onnx to your workspace. In this example, we download the model to the ~/models directory.Run the following command to generate the inception_v3.dlc model.Model quantization
To run a model on Hexagon Tensor Processor (HTP), the converted DLC must be quantized. SNPE offers a tool (snpe-dlc-quant) to quantize a DLC model to INT8/INT16 DLC using its own quantization algorithm. For more information about SNPE quantization, see Quantized models.The quantization process in SNPE requires two steps:
-
Quantization of weights and biases within the model.
Quantization of weights and biases is a static step, i.e., no additional input data is required from the user.
-
Quantization of activation layers (or layers with no weights).
Quantizing activation layers requires a set of input images from a training dataset as calibration data. These calibration dataset images are input as a list of preprocessed image files in
.raw format. The file sizes of these input .raw files must match the input size of the model.
Inputs to snpe-dlc-quant are a converted DLC model and a plain text file with the paths to the calibration dataset images. This input list holds paths to preprocessed images saved as NumPy arrays in .raw format. The size of the preprocessed image must match the input resolution of the model.The output of the snpe-dlc-quant tool is a quantized DLC.Use Netron graph visualization tool to identify the model’s input/output layer dimensions. For demo purposes, we can evaluate the quantization process with random input files. The input file can be generated using a simple Python script shown below for the inception_v3.onnx model. Save the script as generate_random_input.py in your workspace ~/models/ directory and run it using python ~/models/generate_random_input.py on your host computer.The following example Python code creates an input_list that holds paths to calibration dataset images used to quantize the model.The above script generates 10 sample input files saved in the /tmp/RandomInputsForInceptionV3/ directory and an input_list.txt file that contains the path to each sample generated.Now that all needed inputs to the snpe-dlc-quant tool are available, the model can be quantized.This generates a quantized inception_v3 DLC model (inception_v3_quantized.dlc). By default, the model is quantized for INT8 bit width.Customize the quantization to use 16-bit instead of default INT8 by specifying the --act_bitwidth 16 and/or --weights_bitwidth 16 options to the snpe-dlc-quant tool.Refer to the snpe-dlc-quant tool documentation, or run snpe-dlc-quant --help to view all available customizations including quantization modes, optimizations, etc.Model optimization
Quantized model DLC requires a graph preparation step that optimizes the model for execution on HTP. To prepare the model DLC to execute on HTP, SNPE provides a snpe-dlc-graph-prepare tool that takes a quantized model and hardware-specific details, such as chipset, as input.Optimizations for hardware, such as HTP, depend on the specific version of HTP present on the chipset. To ensure the correct set of optimizations are applied to the execution graph for optimal utilization of the HTP, it is important to provide the correct chipset ID to the snpe-dlc-graph-prepare tool.
Based on the HTP version and chipset ID, the tool creates a cache that contains an execution strategy to execute model DLC on the HTP hardware. Without this step, there will be additional overhead during network initialization as the SNPE runtime will have to create an execution strategy on the fly.Once the snpe-dlc-graph-prepare step is completed, the HTP cache record is added to the DLC. This cache information can be viewed using the snpe-dlc-info tool.Port a model using AI Engine Direct
Model conversion and quantization
A pretrained FP32 model from PyTorch, ONNX, TensorFlow, or TFLite is input to the QNN converter tool (qnn-<framework>-converter) to convert to a QNN graph representation in the form of a high-level readable C++ graph.When accelerating the model on HTP, the model must be quantized. Model quantization can be done in the same step as conversion. A calibration dataset must be provided to perform this quantization step to perform static quantization.To enable quantization along with conversion, use the --input_list INPUT_LIST option for static quantization.For more information, see quantization support.The following example uses an ONNX model (inception_v3_opset16.onnx) downloaded from the ONNX Model Zoo.Download the model as inception_v3.onnx to your workspace. In this example, the model is downloaded to the ~/models directory.Model conversion: CPU backend
To convert the model to run on x86/Arm-based CPU, run the following command to generate inception_v3.cpp and inception_v3.bin.The inception_v3.cpp file contains a high-level graph representation of the converted model.The inception_v3.bin file contains weights/biases from the model.Model conversion and quantization: HTP backend
To run the model on HTP, the quantization step is required.For quantization in AI Engine Direct (QNN) SDK, a representative dataset of 50 to 200 images from a training dataset are provided to the QNN converter as a calibration dataset. The images in the calibration dataset are preprocessed (resized, normalized, etc.) and saved as NumPy arrays in .raw format. The size of these input .raw files must match the input size of the model.Use the Netron graph visualization tool to identify the model’s input/output layer dimensions.
For demonstration purposes, you can evaluate the quantization process with random input files. The input files can be generated using the Python script shown below for the inception_v3.onnx model. Save the script as generate_random_input.py in the ~/models/ directory and run it using python ~/models/generate_random_input.py.The following Python code creates an input_list that contains the calibration dataset used to quantize the model.Run the following command to convert and quantize.By default, the model is quantized for INT8 bit width. You can specify --act_bitwidth 16 and/or --weights_bitwidth 16 to use INT16 quantization.This generates inception_v3_quantized.cpp and inception_v3_quantized.bin files in the ~/models/ directory.See qnn-<framework>-converter or run qnn-<framework>-converter --help to view all available customizations to quantization, including quantization modes, optimizations, etc.Model compilation
Once the conversion/quantization step is complete, qnn-model-lib-generator is used to compile the generated C++ graph into a shared object (.so) enabling the model to be dynamically loaded by an application to perform inference.For x86, the Clang compiler toolchain is used to compile the C++ graph into a .so library. For a Linux Embedded device, such as Qualcomm Dragonwing™ RB3 Gen 2 and IQ-9075, the appropriate compiler toolchain (aarch64-oe-linux-gcc11.2) must be used.Compiling a model to run on x86
-
Install the GNU standard C++ library development package for GCC version 12.
This package includes standard library headers (like
<limits>, <vector>, and <string>), static libraries, and support files necessary to compile and link C++ programs.
-
Generate a shared object model to run on an x86-based Linux machine.
This generates
inception_v3.so using the Clang-14 compiler toolchain to compile the C++ graph to a QNN model .so compatible with the x86 host computer.
Compiling a model to run on target
When compiling a model for on-device execution (aarch64 architecture), it is important to use the right cross-compiler toolchain to ensure the compiled shared object (.so) is compatible with the device OS.The following steps install the cross-compiler toolchain required to compile a model cpp file to a .so library. Instructions to install the appropriate cross-compiler toolchain are available under Download and install the Platform SDK.After installing the platform SDK and setting up the cross-compiler environment in a new command line terminal.
-
Check if the environment is properly setup.
If the above environmental variables were not populated, repeat Step 1 in a new command line terminal.
-
Setup the QAIRT environment.
Compiling a model to run on Arm-based CPU
Once the cross-compiler is setup, use the following command to generate libinception_v3.so in ~/model/libs/aarch64-oe-linux-gcc11.2. Provide this location to the qnn-model-lib-generator tool through a command line argument.The compiler toolchain used here is aarch64-oe-linux-gcc11.2.
Compiling a model to run on HTP
To run the model on HTP, the following command generates libinception_v3_quantized.so in ~/models/libs/aarch64-oe-linux-gcc11.2.The compiler toolchain used here is aarch64-oe-linux-gcc11.2.