TPU-MLIR快速入门

news/发布时间2024/5/14 11:38:49
12.1 TPU-MLIR快速入门
12.1.1 TPU-MLIR简介
后文假定用户已经处于docker里面的/workspace目录。
1.编译ONNX模型
以 yolov5s.onnx 为例, 介绍如何编译迁移一个onnx模型至BM1684X TPU平台运行。
该模型来自yolov5的官网: https://github.com/ultralytics/yolov5/releases/download/v6.0/yolov5s.onnx
需要如下文件(其中xxxx对应实际的版本信息):
tpu-MLIR_xxxx.tar.gz (tpu-MLIR的发布包)
2.加载tpu-MLIR
以下操作需要在Docker容器中,代码如下:
//第1章/ tpu-MLIR_envsetup.sh
$ tar zxf tpu-MLIR_xxxx.tar.gz
$ source tpu-MLIR_xxxx/envsetup.sh
envsetup.sh 会添加以下环境变量,见表12-1。
表12-1  环境变量

变量名

说明

TPUC_ROOT

tpu-MLIR_xxx

解压后SDK包的位置

MODEL_ZOO_PATH

${TPUC_ROOT}/../model-zoo

model-zoo文件夹位置, 与SDK在同一级目录

envsetup.sh 对环境变量的修改内容,代码如下:
//第6章/envsetup.sh
export PATH=${TPUC_ROOT}/bin:$PATH
export PATH=${TPUC_ROOT}/python/tools:$PATH
export PATH=${TPUC_ROOT}/python/utils:$PATH
export PATH=${TPUC_ROOT}/python/test:$PATH
export PATH=${TPUC_ROOT}/python/samples:$PATH
export LD_LIBRARY_PATH=$TPUC_ROOT/lib:$LD_LIBRARY_PATH
export PYTHONPATH=${TPUC_ROOT}/python:$PYTHONPATH
export MODEL_ZOO_PATH=${TPUC_ROOT}/../model-zoo
准备工作目录
建立 model_yolov5s 目录, 注意是与tpu-MLIR同级目录; 并把模型文件与图片文件都 放入 model_yolov5s 目录中。
操作代码如下:
//第6章/envsetup.sh
$ mkdir model_yolov5s && cd model_yolov5s
$ cp $TPUC_ROOT/regression/model/yolov5s.onnx.
$ cp -rf $TPUC_ROOT/regression/dataset/COCO2017.
$ cp -rf $TPUC_ROOT/regression/image.
$ mkdir workspace && cd workspace
这里的 $TPUC_ROOT 是环境变量, 对应tpu-MLIR_xxxx目录。
3.ONNX转MLIR
如果模型是图片输入, 在转模型之前需要了解模型的预处理。如果模型用预处理后的npz文件做输入, 则不需要考虑预处理。 预处理过程用如下公式表达 (

 代表输入):

   (6-34)
官网yolov5的图片是rgb, 每个值会乘以 1/255, 转换成均值与缩放对应为 0.0,0.0,0.0 与 0.0039216,0.0039216,0.0039216。
模型转换命令,代码如下:
//第6章/model_transform.py
$ model_transform.py \
    --model_name yolov5s \
    --model_def../yolov5s.onnx \
    --input_shapes [[1,3,640,640]] \
    --mean 0.0,0.0,0.0 \
    --scale 0.0039216,0.0039216,0.0039216 \
    --keep_aspect_ratio \
    --pixel_format rgb \
    --output_names 350,498,646 \
    --test_input../image/dog.jpg \
    --test_result yolov5s_top_outputs.npz \
    --MLIR yolov5s.MLIR \
--post_handle_type yolo
model_transform.py 支持的参数如下:
model_transform 参数功能
4.MLIR转F32模型
将MLIR文件转换成f32的bmodel, 操作方法如下:
//第6章/model_deploy.py
$ model_deploy.py \
    --MLIR yolov5s.MLIR \
    --quantize F32 \
    --chip bm1684x \
    --test_input yolov5s_in_f32.npz \
    --test_reference yolov5s_top_outputs.npz \
    --tolerance 0.99,0.99 \
--model yolov5s_1684x_f32.bmodel
5.MLIR转INT8模型
1)生成校准表
转INT8模型前需要跑校准, 得到校准表; 输入数据的数量根据情况准备100~1000张左右。
然后用校准表, 生成对称或非对称bmodel。如果对称符合需求, 一般不建议用非对称, 因为 非对称的性能会略差于对称模型。
这里用现有的100张来自COCO2017的图片举例, 执行校准,代码如下:
//第6章/run_calibration.py
$ run_calibration.py yolov5s.MLIR \
    --dataset../COCO2017 \
    --input_num 100 \
    -o yolov5s_cali_table
运行完成后会生成名为 ${model_name}_cali_table 的文件, 该文件用于后续编译INT8 模型的输入文件。
2)编译为INT8对称量化模型
转成INT8对称量化模型, 执行命令如下:
//第6章/model_deploy.py
$ model_deploy.py \
    --MLIR yolov5s.MLIR \
    --quantize INT8 \
    --calibration_table yolov5s_cali_table \
    --chip bm1684x \
    --test_input yolov5s_in_f32.npz \
    --test_reference yolov5s_top_outputs.npz \
    --tolerance 0.85,0.45 \
--model yolov5s_1684x_int8_sym.bmodel
编译完成后, 会生成名为 ${model_name}_1684x_int8_sym.bmodel 的文件。
3)编译为INT8非对称量化模型
转成INT8非对称量化模型, 执行命令如下:
//第6章/model_deploy_yolov5s.py
$ model_deploy.py \
    --MLIR yolov5s.MLIR \
    --quantize INT8 \
    --asymmetric \
    --calibration_table yolov5s_cali_table \
    --chip bm1684x \
    --test_input yolov5s_in_f32.npz \
    --test_reference yolov5s_top_outputs.npz \
    --tolerance 0.90,0.55 \
--model yolov5s_1684x_int8_asym.bmodel
编译完成后, 会生成名为 ${model_name}_1684x_int8_asym.bmodel 的文件。
6.效果对比
在本发布包中有用python写好的yolov5用例, 源码路径 $TPUC_ROOT/python/samples/detect_yolov5.py,用于对图片进行目标检测。阅读该 代码可以了解模型是如何使用的: 先预处理得到模型的输入, 然后推理得到输出, 最后做后处理。
验证onnx/f32/int8的执行结果,代码如下:
//第6章/detect_bmodel_yolov5.py
onnx模型的执行方式如下, 得到 dog_onnx.jpg:
$ detect_yolov5.py \
    --input../image/dog.jpg \
    --model../yolov5s.onnx \
    --output dog_onnx.jpg
f32 bmodel的执行方式如下, 得到 dog_f32.jpg:
$ detect_yolov5.py \
    --input../image/dog.jpg \
    --model yolov5s_1684x_f32.bmodel \
    --output dog_f32.jpg
int8对称bmodel的执行方式如下, 得到 dog_int8_sym.jpg:
$ detect_yolov5.py \
    --input../image/dog.jpg \
    --model yolov5s_1684x_int8_sym.bmodel \
    --output dog_int8_sym.jpg
int8非对称bmodel的执行方式如下, 得到 dog_int8_asym.jpg:
$ detect_yolov5.py \
    --input../image/dog.jpg \
    --model yolov5s_1684x_int8_asym.bmodel \
--output dog_int8_asym.jpg
四张图片对比,如图12-1所示。
 
图12-1  四张图片结果对比示例
由于运行环境不同, 最终的效果与精度与图12-1 会有些差异。
1)模型性能测试
以下操作需要在Docker外执行,
2)安装 libsophon 环境
请参考 libsophon 使用手册安装 libsophon。
3)检查 BModel 的性能
安装好 libsophon 后, 可以使用 bmrt_test 来测试编译出的 bmodel 的正确 性及性能。可以根据 bmrt_test 输出的性能结果, 来估算模型最大的fps, 来选择合适的模型,代码如下:
//第6章/test_bmodel_yolov5s.py
# 下面测试上面编译出的bmodel
# --bmodel参数后面接bmodel文件,
 
$ cd $TPUC_ROOT/../model_yolov5s/workspace
$ bmrt_test --bmodel yolov5s_1684x_f32.bmodel
$ bmrt_test --bmodel yolov5s_1684x_int8_asym.bmodel
$ bmrt_test --bmodel yolov5s_1684x_int8_sym.bmodel
以最后一个命令输出为例(此处对日志做了部分截断处理):
[BMRT][load_bmodel:983] INFO:pre net num: 0, load net num: 1
[BMRT][show_net_info:1358] INFO: ########################
[BMRT][show_net_info:1359] INFO: NetName: yolov5s, Index=0
[BMRT][show_net_info:1361] INFO: ---- stage 0 ----
[BMRT][show_net_info:1369] INFO:   input 0) 'images' shape=[ 1 3 640 640 ] dtype=FLOAT32
[BMRT][show_net_info:1378] INFO:   output 0) '350_Transpose_f32' shape=[ 1 3 80 80 85 ]...
[BMRT][show_net_info:1378] INFO:   output 1) '498_Transpose_f32' shape=[ 1 3 40 40 85 ]...
[BMRT][show_net_info:1378] INFO:   output 2) '646_Transpose_f32' shape=[ 1 3 20 20 85 ]...
[BMRT][show_net_info:1381] INFO: ########################
[BMRT][bmrt_test:770] INFO:==> running network #0, name: yolov5s, loop: 0
[BMRT][bmrt_test:834] INFO:reading input #0, bytesize=4915200
[BMRT][print_array:702] INFO:  --> input_data: < 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0...
[BMRT][bmrt_test:982] INFO:reading output #0, bytesize=6528000
[BMRT][print_array:702] INFO:  --> output ref_data: < 0 0 0 0 0 0 0 0 0 0 0 0 0 0...
[BMRT][bmrt_test:982] INFO:reading output #1, bytesize=1632000
[BMRT][print_array:702] INFO:  --> output ref_data: < 0 0 0 0 0 0 0 0 0 0 0 0 0 0...
[BMRT][bmrt_test:982] INFO:reading output #2, bytesize=408000
[BMRT][print_array:702] INFO:  --> output ref_data: < 0 0 0 0 0 0 0 0 0 0 0 0 0 0...
[BMRT][bmrt_test:1014] INFO:net[yolov5s] stage[0], launch total time is 4122 us (npu 4009 us, cpu 113 us)
[BMRT][bmrt_test:1017] INFO:+++ The network[yolov5s] stage[0] output_data +++
[BMRT][print_array:702] INFO:output data #0 shape: [1 3 80 80 85 ] < 0.301003   ...
[BMRT][print_array:702] INFO:output data #1 shape: [1 3 40 40 85 ] < 0 0.228689 ...
[BMRT][print_array:702] INFO:output data #2 shape: [1 3 20 20 85 ] < 1.00135    ...
[BMRT][bmrt_test:1058] INFO:load input time(s): 0.008914
[BMRT][bmrt_test:1059] INFO:calculate  time(s): 0.004132
[BMRT][bmrt_test:1060] INFO:get output time(s): 0.012603
[BMRT][bmrt_test:1061] INFO:compare    time(s): 0.006514
从上面输出可以看到以下信息:
1)05-08行是bmodel的网络输入输出信息
2)19行是在TPU上运行的时间, 其中TPU用时4009us, CPU用时113us。这里CPU用时主要是指在HOST端调用等待时间
3)24行是加载数据到NPU的DDR的时间
4)25行相当于12行的总时间
5)26行是输出数据取回时间
7.编译TFLite模型
以 resnet50_int8.tflite 模型为例, 介绍如何编译迁移一个TFLite模型至BM1684X TPU平台运行。
需要如下文件(其中xxxx对应实际的版本信息):
tpu-MLIR_xxxx.tar.gz (tpu-MLIR的发布包)
1)加载tpu-MLIR
以下操作需要在Docker容器中,命令如下:
//第6章/envsetup_tpu-MLIR.py
$ tar zxf zxf tpu-MLIR_xxxx.tar.gz
$ source tpu-MLIR_xxxx/envsetup.sh
envsetup.sh 会添加以下环境变量:
环境变量
envsetup.sh 对环境变量的修改内容为:
export PATH=${TPUC_ROOT}/bin:$PATH
export PATH=${TPUC_ROOT}/python/tools:$PATH
export PATH=${TPUC_ROOT}/python/utils:$PATH
export PATH=${TPUC_ROOT}/python/test:$PATH
export PATH=${TPUC_ROOT}/python/samples:$PATH
export LD_LIBRARY_PATH=$TPUC_ROOT/lib:$LD_LIBRARY_PATH
export PYTHONPATH=${TPUC_ROOT}/python:$PYTHONPATH
export MODEL_ZOO_PATH=${TPUC_ROOT}/../model-zoo
2)准备工作目录
建立 model_resnet50_tf 目录, 注意是与tpu-MLIR同级目录; 并把测试图片文件放入 model_resnet50_tf 目录中。
操作命令如下:
//第6章/model_resnet50_tf.py
$ mkdir model_resnet50_tf && cd model_resnet50_tf
$ cp $TPUC_ROOT/regression/model/resnet50_int8.tflite.
$ cp -rf $TPUC_ROOT/regression/image.
$ mkdir workspace && cd workspace
这里的 $TPUC_ROOT 是环境变量, 对应tpu-MLIR_xxxx目录。
3)TFLite转MLIR
本例中的模型是bgr输入, 均值为 103.939,116.779,123.68, 缩放为 1.0,1.0,1.0
模型转换,命令如下:
//第6章/model_transform_resnet50.py
$ model_transform.py \
    --model_name resnet50_tf \
    --model_def ../resnet50_int8.tflite \
    --input_shapes [[1,3,224,224]] \
    --mean 103.939,116.779,123.68 \
    --scale 1.0,1.0,1.0 \
    --pixel_format bgr \
    --test_input../image/cat.jpg \
    --test_result resnet50_tf_top_outputs.npz \
    --MLIR resnet50_tf.MLIR
转成MLIR文件后, 会生成一个 resnet50_tf_in_f32.npz 文件, 该文件是模型的输入文件。
4)MLIR转模型
该模型是tflite非对称量化模型, 可以按参数转成模型,代码如下:
//第6章/model_deploy_resnet50.py
$ model_deploy.py \
    --MLIR resnet50_tf.MLIR \
    --quantize INT8 \
    --asymmetric \
    --chip bm1684x \
    --test_input resnet50_tf_in_f32.npz \
    --test_reference resnet50_tf_top_outputs.npz \
    --model resnet50_tf_1684x.bmodel
编译完成后, 会生成名为 resnet50_tf_1684x.bmodel 的文件。
8.编译Caffe模型
以 mobilenet_v2_deploy.prototxt 与 mobilenet_v2.caffemodel 为例, 介绍如何编译迁移一个caffe模型至BM1684X TPU平台运行。
需要如下文件(其中xxxx对应实际的版本信息):
tpu-MLIR_xxxx.tar.gz (tpu-MLIR的发布包)
加载tpu-MLIR
以下操作需要在Docker容器中,代码如下:
//第6章/model_envsetup_tpu-MLIR.py
$ tar zxf tpu-MLIR_xxxx.tar.gz
$ source tpu-MLIR_xxxx/envsetup.sh
envsetup.sh 会添加以下环境变量:
环境变量
envsetup.sh 对环境变量的修改内容为:
export PATH=${TPUC_ROOT}/bin:$PATH
export PATH=${TPUC_ROOT}/python/tools:$PATH
export PATH=${TPUC_ROOT}/python/utils:$PATH
export PATH=${TPUC_ROOT}/python/test:$PATH
export PATH=${TPUC_ROOT}/python/samples:$PATH
export LD_LIBRARY_PATH=$TPUC_ROOT/lib:$LD_LIBRARY_PATH
export PYTHONPATH=${TPUC_ROOT}/python:$PYTHONPATH
export MODEL_ZOO_PATH=${TPUC_ROOT}/../model-zoo
准备工作目录
建立 mobilenet_v2 目录, 注意是与tpu-MLIR同级目录; 并把模型文件与图片文件都 放入 mobilenet_v2 目录中。
操作命令如下:
//第6章/model_mobilenet_v2.py
$ mkdir mobilenet_v2 && cd mobilenet_v2
$ cp $TPUC_ROOT/regression/model/mobilenet_v2_deploy.prototxt.
$ cp $TPUC_ROOT/regression/model/mobilenet_v2.caffemodel.
$ cp -rf $TPUC_ROOT/regression/dataset/ILSVRC2012.
$ cp -rf $TPUC_ROOT/regression/image.
$ mkdir workspace && cd workspace
这里的 $TPUC_ROOT 是环境变量, 对应tpu-MLIR_xxxx目录。
Caffe转MLIR
本例中的模型是 BGR 输入, 均值与缩放分别为 103.94,116.78,123.68 与 0.017,0.017,0.017。
模型转换,命令如下:
//第6章/transform_mobilenet_v2.py
$ model_transform.py \
    --model_name mobilenet_v2 \
    --model_def../mobilenet_v2_deploy.prototxt \
    --model_data../mobilenet_v2.caffemodel \
    --input_shapes [[1,3,224,224]] \
    --resize_dims=256,256 \
    --mean 103.94,116.78,123.68 \
    --scale 0.017,0.017,0.017 \
    --pixel_format bgr \
    --test_input../image/cat.jpg \
    --test_result mobilenet_v2_top_outputs.npz \
--MLIR mobilenet_v2.MLIR
 
转成MLIR文件后, 会生成一个 ${model_name}_in_f32.npz 文件, 该文件是模型的输入文件。
MLIR转F32模型
将MLIR文件转换成f32的bmodel, 操作方法如下:
//第6章/model_deploy_mobilenet_v2.py
$ model_deploy.py \
    --MLIR mobilenet_v2.MLIR \
    --quantize F32 \
    --chip bm1684x \
    --test_input mobilenet_v2_in_f32.npz \
    --test_reference mobilenet_v2_top_outputs.npz \
    --tolerance 0.99,0.99 \
    --model mobilenet_v2_1684x_f32.bmodel
编译完成后, 会生成名为 ${model_name}_1684x_f32.bmodel 的文件。
MLIR转INT8模型
生成校准表
转INT8模型前需要跑校准, 得到校准表; 输入数据的数量根据情况准备100~1000张左右。
然后用校准表, 生成对称或非对称bmodel。如果对称符合需求, 一般不建议用非对称, 因为 非对称的性能会略差于对称模型。
这里用现有的100张来自ILSVRC2012的图片举例, 执行校准,命令如下:
//第6章/calibration _mobilenet_v2.py
$ run_calibration.py mobilenet_v2.MLIR \
    --dataset../ILSVRC2012 \
    --input_num 100 \
    -o mobilenet_v2_cali_table
运行完成后会生成名为 ${model_name}_cali_table 的文件, 该文件用于后续编译INT8 模型的输入文件。
编译为INT8对称量化模型
转成INT8对称量化模型, 执行命令如下:
//第6章/mlir_calibration_mobilenet_v2.py
$ model_deploy.py \
    --MLIR mobilenet_v2.MLIR \
    --quantize INT8 \
    --calibration_table mobilenet_v2_cali_table \
    --chip bm1684x \
    --test_input mobilenet_v2_in_f32.npz \
    --test_reference mobilenet_v2_top_outputs.npz \
    --tolerance 0.96,0.70 \
--model mobilenet_v2_1684x_int8_sym.bmodel
编译完成后, 会生成名为 ${model_name}_1684x_int8_sym.bmodel 的文件。
编译为INT8非对称量化模型
转成INT8非对称量化模型, 执行命令如下:
//第6章/mlir_asymmetric_mobilenet_v2.py
$ model_deploy.py \
    --MLIR mobilenet_v2.MLIR \
    --quantize INT8 \
    --asymmetric \
    --calibration_table mobilenet_v2_cali_table \
    --chip bm1684x \
    --test_input mobilenet_v2_in_f32.npz \
    --test_reference mobilenet_v2_top_outputs.npz \
    --tolerance 0.95,0.69 \
--model mobilenet_v2_1684x_int8_asym.bmodel
编译完成后, 会生成名为 ${model_name}_1684x_int8_asym.bmodel 的文件。
1)混精度使用方法
以检测网络 yolov3 tiny 网络模型为例, 介绍如何使用混精度。 该模型来自https://github.com/onnx/models/tree/main/vision/object_detection_segmentation/tiny-yolov3。
需要如下文件(其中xxxx对应实际的版本信息):
tpu-MLIR_xxxx.tar.gz (tpu-MLIR的发布包)
2)加载tpu-MLIR
以下操作需要在Docker容器中,命令如下:
//第6章/tpu_mlir_envsetup.py
$ tar zxf tpu-MLIR_xxxx.tar.gz
$ source tpu-MLIR_xxxx/envsetup.sh
envsetup.sh 会添加以下环境变量:
envsetup.sh 对环境变量的修改内容为:
export PATH=${TPUC_ROOT}/bin:$PATH
export PATH=${TPUC_ROOT}/python/tools:$PATH
export PATH=${TPUC_ROOT}/python/utils:$PATH
export PATH=${TPUC_ROOT}/python/test:$PATH
export PATH=${TPUC_ROOT}/python/samples:$PATH
export LD_LIBRARY_PATH=$TPUC_ROOT/lib:$LD_LIBRARY_PATH
export PYTHONPATH=${TPUC_ROOT}/python:$PYTHONPATH
export MODEL_ZOO_PATH=${TPUC_ROOT}/../model-zoo
3)准备工作目录
建立 yolov3_tiny 目录, 注意是与tpu-MLIR同级目录; 并把模型文件与图片文件都 放入 yolov3_tiny 目录中。
操作命令如下:
//第6章/wget_envsetup.py
$ mkdir yolov3_tiny && cd yolov3_tiny
 $ wget https://github.com/onnx/models/raw/main/vision/object_detection_segmentation/tiny-yolov3/model/tiny-yolov3-11.onnx
 $ cp -rf $TPUC_ROOT/regression/dataset/COCO2017.
 $ mkdir workspace && cd workspace
 
$ tar zxf tpu-MLIR_xxxx.tar.gz
$ source tpu-MLIR_xxxx/envsetup.sh
envsetup.sh 会添加以下环境变量:
envsetup.sh 对环境变量的修改内容为:
export PATH=${TPUC_ROOT}/bin:$PATH
export PATH=${TPUC_ROOT}/python/tools:$PATH
export PATH=${TPUC_ROOT}/python/utils:$PATH
export PATH=${TPUC_ROOT}/python/test:$PATH
export PATH=${TPUC_ROOT}/python/samples:$PATH
export LD_LIBRARY_PATH=$TPUC_ROOT/lib:$LD_LIBRARY_PATH
export PYTHONPATH=${TPUC_ROOT}/python:$PYTHONPATH
export MODEL_ZOO_PATH=${TPUC_ROOT}/../model-zoo
这里的 $TPUC_ROOT 是环境变量, 对应tpu-MLIR_xxxx目录。 注意如果 tiny-yolov3-11.onnx 用wget下载失败, 请用其他方式下载后放到 yolov3_tiny 目录。
4)验证原始模型
detect_yolov3.py 是已经写好的验证程序, 可以用来对 yolov3_tiny 网络进行验证。执行过程,命令如下:
//第6章/detect_yolov3.py
$ detect_yolov3.py \
     --model../tiny-yolov3-11.onnx \
     --input../COCO2017/000000366711.jpg \
     --output yolov3_onnx.jpg
执行完后输出检测到的结果如下:
person:60.7%
orange:77.5%
并得到图片 yolov3_onnx.jpg, yolov3_tiny ONNX执行效果,如图12-2所示。                                                                                                                                       
 
图12-2  yolov3_tiny ONNX执行效果示例
12.1.2 转成INT8对称量化模型
如前面介绍的转模型方法, 这里不做参数说明, 只有操作过程,命令如下:
//第6章/yolov3_tiny.py
第一步: 转成F32 MLIR
$ model_transform.py \
    --model_name yolov3_tiny \
    --model_def../tiny-yolov3-11.onnx \
    --input_shapes [[1,3,416,416]] \
    --scale 0.0039216,0.0039216,0.0039216 \
    --pixel_format rgb \
    --keep_aspect_ratio \
    --pad_value 128 \
    --output_names=transpose_output1,transpose_output \
    --MLIR yolov3_tiny.MLIR
第二步: 生成calibartion table
$ run_calibration.py yolov3_tiny.MLIR \
    --dataset../COCO2017 \
    --input_num 100 \
    -o yolov3_cali_table
第三步: 转对称量化模型
$ model_deploy.py \
    --MLIR yolov3_tiny.MLIR \
    --quantize INT8 \
    --calibration_table yolov3_cali_table \
    --chip bm1684x \
    --model yolov3_int8.bmodel
第四步: 验证模型
$ detect_yolov3.py \
     --model yolov3_int8.bmodel \
     --input../COCO2017/000000366711.jpg \
     --output yolov3_int8.jpg
执行完后有如下输出信息,表示检测到一个目标:
                  orange:73.0%
得到图片 yolov3_int8.jpg,  yolov3_tiny int8对称量化执行效果,如图12-3所示。
 
图12-3  yolov3_tiny ONNX执行效果示例
可以看出int8对称量化模型相对原始模型, 在这张图上效果不佳,只检测到一个目标。
1)转成混精度量化模型
在转int8对称量化模型的基础上, 执行如下步骤。
2)生成混精度量化表
使用 run_qtable.py 生成混精度量化表, 相关参数说明如下:
3)run_qtable.py 参数功能
本例中采用默认10张图片校准, 对于CV18xx系列的芯片,将chip设置为对应的芯片名称即可,执行命令,代码如下:
//第6章/run_qtable_yolov3_tiny.py
$ run_qtable.py yolov3_tiny.MLIR \
    --dataset../COCO2017 \
    --calibration_table yolov3_cali_table \
    --chip bm1684x \
    --min_layer_cos 0.999 \ #若这里使用默认的0.99时,程序会检测到原始int8模型已满足0.99的cos,从而直接不再搜素
    --expected_cos 0.9999 \
    -o yolov3_qtable
执行完后最后输出如下输出:
int8 outputs_cos:0.999317
mix model outputs_cos:0.999739
output mix quantization table to yolov3_qtable
total time:44 second
上面int8 outputs_cos表示int8模型原本网络输出与fp32的cos相似度,mix model outputs_cos表示部分层使用混精度后网络输出的cos相似度,total time表示搜索时间为44秒, 另外,生成的混精度量化表 yolov3_qtable, 内容如下:
# op_name   quantize_mode
convolution_output11_convF16
model_1/leaky_re_lu_2/LeakyRelu:0_LeakyRelu F16
model_1/leaky_re_lu_2/LeakyRelu:0_pooling0_MaxPool F16
convolution_output10_convF16
convolution_output9_convF16
model_1/leaky_re_lu_4/LeakyRelu:0_LeakyRelu F16
model_1/leaky_re_lu_5/LeakyRelu:0_LeakyRelu F16
model_1/leaky_re_lu_5/LeakyRelu:0_pooling0_MaxPool F16
model_1/concatenate_1/concat:0_Concat F16
该表中, 第一列表示相应的layer, 第二列表示类型, 支持的类型有F32/F16/BF16/INT8。 另外同时也会生成一个loss表文件 full_loss_table.txt, 内容如下:
# chip: bm1684x  mix_mode: F16
###
No.0  : Layer:convolution_output11_conv                           Cos: 0.984398
No.1  : Layer: model_1/leaky_re_lu_5/LeakyRelu:0_LeakyRelu          Cos: 0.998341
No.2  : Layer: model_1/leaky_re_lu_2/LeakyRelu:0_pooling0_MaxPool   Cos: 0.998500
No.3  : Layer:convolution_output9_conv                            Cos: 0.998926
No.4  : Layer:convolution_output8_conv                            Cos: 0.999249
No.5  : Layer: model_1/leaky_re_lu_4/LeakyRelu:0_pooling0_MaxPool   Cos: 0.999284
No.6  : Layer: model_1/leaky_re_lu_1/LeakyRelu:0_LeakyRelu          Cos: 0.999368
No.7  : Layer: model_1/leaky_re_lu_3/LeakyRelu:0_LeakyRelu          Cos: 0.999554
No.8  : Layer: model_1/leaky_re_lu_1/LeakyRelu:0_pooling0_MaxPool   Cos: 0.999576
No.9  : Layer: model_1/leaky_re_lu_3/LeakyRelu:0_pooling0_MaxPool   Cos: 0.999723
No.10 : Layer:convolution_output12_conv                           Cos: 0.999810
该表按cos从小到大顺利排列, 表示该层的前驱Layer根据各自的cos已换成相应的浮点模式后, 该层计算得到的cos, 若该cos仍小于前面min_layer_cos参数,则会将该层及直接后继层设置为浮点计算。 run_qtable.py 会在每次设置某相邻2层为浮点计算后,接续计算整个网络的输出cos,若该cos大于指定的expected_cos,则退出搜素。因此,若设置更大的expected_cos,会尝试将更多层设为浮点计算
第二步: 生成混精度量化模型
$ model_deploy.py \
    --MLIR yolov3_tiny.MLIR \
    --quantize INT8 \
    --quantize_table yolov3_qtable \
    --calibration_table yolov3_cali_table \
    --chip bm1684x \
    --model yolov3_mix.bmodel
第三步: 验证混精度模型
$ detect_yolov3.py \
     --model yolov3_mix.bmodel \
     --input../COCO2017/000000366711.jpg \
     --output yolov3_mix.jpg
执行完后输出结果为:
person:63.9%
orange:73.0%
得到图片yolov3_mix.jpg, yolov3_tiny 混精度对称量化执行效果,如图12-4所示。
 
图12-4  yolov3_tiny 混精度对称量化执行效果
可以看出混精度后, 检测结果更接近原始模型的结果。
需要说明的是,除了使用run_qtable生成量化表外,也可根据模型中每一层的相似度对比结果,自行设置量化表中需要做混精度量化的OP的名称与量化类型。
3)使用TPU做前处理
目前TPU-MLIR支持的两个主要系列芯片BM168x与CV18xx均支持将图像常见的预处理加入到模型中进行计算。开发者可以在模型编译阶段,通过编译选项传递相应预处理参数,由编译器直接在模型运算前插⼊相应前处理算⼦,⽣成的bmodel或cvimodel即可以直接以预处理前的图像作为输⼊,随模型推理过程使⽤TPU处理前处理运算,见表12-2。
表12-2  预处理类型支持情况

预处理类型

BM168X

CV18XX

图像裁剪

True

True

归一化计算

True

True

NHWC to NCHW

True

True

BGR/RGB 转换

True

True

其中图像裁剪会先将图片按使用model_transform工具时输入的–resize_dims参数,将图片调整为对应的大小, 再裁剪成模型输入的尺寸。而归一化计算支持直接将未进行预处理的图像数据(即无符号的int8格式的数据)做归一化处理。
若要将预处理融入到模型中, 则需要在使用model_deploy工具进行部署时使用–fuse_preprocess参数。如果要做验证, 则传入的test_input需要是图像原始格式的输入(即jpg, jpeg与png格式), 相应地会生成原始图像输入对应的npz文件,名称为 ${model_name}_in_ori.npz。
此外, 当实际外部输入格式与模型的格式不相同时, 用–customization_format指定实际的外部输入格式, 支持的格式说明,见表12-3。
表12-3  customization_format格式与说明

CUSTOMIZATION_FORMAT

说明

BM1684X

CV18XX

None

与原始模型输入保持一致, 不做处理。默认

True

True

RGB_PLANAR

rgb顺序,按照nchw摆放

True

True

RGB_PACKED

rgb顺序,按照nhwc摆放

True

True

BGR_PLANAR

bgr顺序,按照nchw摆放

True

True

BGR_PACKED

bgr顺序,按照nhwc摆放

True

True

GRAYscale

仅有⼀个灰⾊通道,按nchw摆

True

True

YUV420_PLANAR

yuv420 planner格式,来⾃vpss的输⼊

False

True

YUV_NV21

yuv420的NV21格式,来⾃vpss的输⼊

False

True

YUV_NV12

yuv420的NV12格式,来⾃vpss的输⼊

False

True

RGBA_PLANAR

rgba格式,按照nchw摆放

False

True

其中YUV*类格式为CV18xx系列芯片特有的输入格式。当customization_format中颜色通道的顺序与模型输入不同时, 将会进行通道转换操作。若指令中未设置customization_format参数,则根据使用model_transform工具时定义的pixel_format与channel_format参数自动获取对应的customization_format。
模型部署样例
以mobilenet_v2模型为例, 参考编译Caffe模型, 在tpu-MLIR/regression/regression_out/目录下使用model_transform工具生成原始MLIR, 并通过run_calibration工具生成校准表。
4)BM1684X部署
生成融合预处理的INT8对称量化bmodel模型,指令如下:
//第6章/test_model_deploy.py
$ model_deploy.py \
    --MLIR mobilenet_v2.MLIR \
    --quantize INT8 \
    --calibration_table mobilenet_v2_cali_table \
    --chip bm1684x \
    --test_input../image/cat.jpg \
    --test_reference mobilenet_v2_top_outputs.npz \
    --tolerance 0.96,0.70 \
    --fuse_preprocess \
--model mobilenet_v2_bm1684x_int8_sym_fuse_preprocess.bmodel
5)CV18xx部署
生成融合预处理的INT8对称量化cvimodel模型,指令如下:
//第6章/sym_fuse_preprocess.cvimodel.py
$ model_deploy.py \
    --MLIR mobilenet_v2.MLIR \
    --quantize INT8 \
    --calibration_table mobilenet_v2_cali_table \
    --chip cv183x \
    --test_input../image/cat.jpg \
    --test_reference mobilenet_v2_top_outputs.npz \
    --tolerance 0.96,0.70 \
    --fuse_preprocess \
    --customization_format RGB_PLANAR \
--model mobilenet_v2_cv183x_int8_sym_fuse_preprocess.cvimodel
当输入数据是来自于CV18xx提供的视频后处理模块VPSS时,则会有数据对齐要求,⽐如w 按照32字节对齐,此时生成融合预处理的cvimodel模型,指令如下:
//第6章/sym_fuse_preprocess_aligned.cvimodel.py
$ model_deploy.py \
    --MLIR mobilenet_v2.MLIR \
    --quantize INT8 \
    --calibration_table mobilenet_v2_cali_table \
    --chip cv183x \
    --test_input../image/cat.jpg \
    --test_reference mobilenet_v2_top_outputs.npz \
    --tolerance 0.96,0.70 \
    --fuse_preprocess \
    --customization_format RGB_PLANAR \
    --aligned_input \
--model mobilenet_v2_cv183x_int8_sym_fuse_preprocess_aligned.cvimodel
上述指令中,aligned_input指定了模型需要做输入的对齐。需要注意的是,YUV格式的输入数据fuse_preprocess与aligned_input需要都做,其它格式的fuse_preprocess与aligned_input的操作可选择只做其中一个或两个都做, 若只做aligned_input操作,则需要设置test_input为做过预处理的 ${model_name}_in_f32.npz 格式,与编译ONNX模型的设置是一致的。
12.2 各框架模型转ONNX参考
主要提供了将PyTorch, Tensorflow与PaddlePaddle模型转为ONNX模型的方式参考,读者也可以参考ONNX官方仓库提供的转模型教程: https://github.com/onnx/tutorials。
PyTorch模型转ONNX
以一个自主搭建的简易PyTorch模型为例进行onnx转换,代码如下:
//第6章/torch_model.py
步骤0:创建工作目录
在命令行中创建并进入torch_model目录。
$ mkdir torch_model
$ cd torch_model
步骤1:搭建并保存模型
在该目录下创建名为simple_net.py的脚本并运行,脚本的具体内容如下:
#!/usr/bin/env python3
import torch
 
# 构建简单的神经网络模型
class SimpleModel(torch.nn.Module):
 
   def __init__(self):
      super(SimpleModel, self).__init__()
      self.m1 = torch.nn.conv2d(3, 8, 3, 1, 0)
      self.m2 = torch.nn.conv2d(8, 8, 3, 1, 1)
 
   def forward(self,x):
      y0 = self.m1(x)
      y1 = self.m2(y0)
      y2 = y0 + y1
      return y2
 
# 创建一个SimpleModel并将其权重保存在当前目录中
model = SimpleModel()
torch.save(model.state_dict(), weight.pth)
运行完后会在当前目录下获得一个weight.pth的权重文件。
步骤2:导出ONNX模型
在该目录下创建另一个名为export_onnx.py的脚本并运行,脚本的具体内容如下:
#!/usr/bin/env python3
import torch
from simple_net import SimpleModel
 
# 加载预训练的模型并将其导出为onnx
model = SimpleModel()
model.eval()
checkpoint = torch.load(weight.pth, map_location=cpu)
model.load_state_dict(checkpoint)
 
# 准备输入张量
input = torch.randn(1, 3, 16, 16, requires_grad=True)
 
# 将torch模型导出为onnx
torch.onnx.export(model,
                  input,
                  'model.onnx', # 导出的onnx模型的名称
                  opset_version=13,
                  export_params=True,
                  do_constant_folding=True)
运行完脚本后,即可在当前目录下得到名为model.onnx的onnx模型。
1.Tensorflow模型转ONNX
以Tensorflow官方仓库中提供的mobilenet_v1_0.25_224模型作为转换样例,命令如下:
//第6章/tf_model_onnx.py
步骤0:创建工作目录
在命令行中创建并进入tf_model目录。
$ mkdir tf_model
$ cd tf_model
步骤1:准备并转换模型
命令行中通过以下命令下载模型并利用tf2onnx工具将其导出为ONNX模型:
$ wget -nc http://download.tensorflow.org/models/mobilenet_v1_2018_08_02/mobilenet_v1_0.25_224.tgz
# tar获取*.pb模型定义文件
$ tar xzf mobilenet_v1_0.25_224.tgz
$ python -m tf2onnx.convert --graphdef mobilenet_v1_0.25_224_frozen.pb \
    --output mnet_25.onnx --inputs input:0 \
    --inputs-as-nchw input:0 \
    --outputs MobilenetV1/Predictions/Reshape_1:0
运行以上所有命令后即可在当前目录下得到名为mnet_25.onnx的onnx模型。
2.PaddlePaddle模型转ONNX
以PaddlePaddle官方仓库中提供的SqueezeNet1_1模型作为转换样例,命令如下:
//第6章/pp_model_onnx.py
步骤0:创建工作目录
在命令行中创建并进入pp_model目录。
$ mkdir pp_model
$ cd pp_model
步骤1:准备模型
在命令行中通过以下命令下载模型:
$ wget https://bj.bcebos.com/paddlehub/fastdeploy/SqueezeNet1_1_infer.tgz
$ tar xzf SqueezeNet1_1_infer.tgz
$ cd SqueezeNet1_1_infer
并用PaddlePaddle项目中的paddle_infer_shape.py脚本对模型进行shape推理,此处将输入shape以NCHW的格式设置为[1,3,224,224]:
$ wget https://raw.githubusercontent.com/PaddlePaddle/Paddle2ONNX/develop/tools/paddle/paddle_infer_shape.py
$ python paddle_infer_shape.py  --model_dir. \
                          --model_filename inference.pdmodel \
                          --params_filename inference.pdiparams \
                          --save_dir new_model \
                          --input_shape_dict={'inputs':[1,3,224,224]}
运行完以上所有命令后将处于SqueezeNet1_1_infer目录下,并在该目录下有一个new_model的目录。
步骤2:转换模型
在命令行中通过以下命令安装paddle2onnx工具,并利用该工具将PaddlePaddle模型转为ONNX模型:
$ pip install paddle2onnx
$ paddle2onnx  --model_dir new_model \
          --model_filename inference.pdmodel \
          --params_filename inference.pdiparams \
          --opset_version 13 \
          --save_file squeezenet1_1.onnx
运行完以上所有命令后将获得一个名为squeezenet1_1.onnx的onnx模型。
3.CV18xx芯片使用指南
CV18xx支持ONNX系列与Caffe模型,目前不支持TFLite模型。在量化数据类型方面,CV18xx支持BF16格式的量化 与INT8格式的非对称量化。节以CV183X芯片为例,介绍CV18xx系列芯片编译模型与运行runtime sample。
编译yolov5模型
加载tpu-MLIR
以下操作需要在Docker容器中,命令如下:
//第6章/tpu-MLIR_envsetup.py
$ tar zxf tpu-MLIR_xxxx.tar.gz
$ source tpu-MLIR_xxxx/envsetup.sh
envsetup.sh 会添加以下环境变量:
操作如下:
$ mkdir model_yolov5s && cd model_yolov5s
$ cp $TPUC_ROOT/regression/model/yolov5s.onnx.
$ cp -rf $TPUC_ROOT/regression/dataset/COCO2017.
$ cp -rf $TPUC_ROOT/regression/image.
$ mkdir workspace && cd workspace
这里的 $TPUC_ROOT 是环境变量, 对应tpu-MLIR_xxxx目录。
这里的 $TPUC_ROOT 是环境变量, 对应tpu-MLIR_xxxx目录。
12.2.1 ONNX转MLIR
如果模型是图片输入, 在转模型之前需要了解模型的预处理。如果模型用预处理后的npz文件做输入, 则不需要考虑预处理。 预处理过程用公式表达如下(

 代表输入):

 官网yolov5的图片是RGB格式, 每个值会乘以 1/255, 转换成均值与缩放对应为 0.0,0.0,0.0 与 0.0039216,0.0039216,0.0039216,命令如下:

//第6章/model_transform_deploy_calibration.py
模型转换命令如下:
$ model_transform.py \
    --model_name yolov5s \
    --model_def../yolov5s.onnx \
    --input_shapes [[1,3,640,640]] \
    --mean 0.0,0.0,0.0 \
    --缩放 0.0039216,0.0039216,0.0039216 \
    --keep_aspect_ratio \
    --pixel_format rgb \
    --output_names 350,498,646 \
    --test_input../image/dog.jpg \
    --test_result yolov5s_top_outputs.npz \
    --MLIR yolov5s.MLIR
model_transform 的相关参数说明参考编译ONNX模型-ONNX转MLIR部分。
MLIR转BF16模型
将MLIR文件转换成bf16的cvimodel, 操作方法如下:
$ model_deploy.py \
    --MLIR yolov5s.MLIR \
    --quantize BF16 \
    --chip cv183x \
    --test_input yolov5s_in_f32.npz \
    --test_reference yolov5s_top_outputs.npz \
    --tolerance 0.99,0.99 \
    --model yolov5s_cv183x_bf16.cvimodel
model_deploy.py 的相关参数说明参考编译ONNX模型-MLIR转F32模型部分。
MLIR转INT8模型
转INT8模型前需要跑calibration, 得到校准表; 输入数据的数量根据情况准备100~1000张左右。然后用校准表, 生成INT8对称cvimodel
这里用现有的100张来自COCO2017的图片举例, 执行calibration:
$ run_calibration.py yolov5s.MLIR \
    --dataset../COCO2017 \
    --input_num 100 \
    -o yolov5s_cali_table
运行完成后会生成名为 ${model_name}_cali_table 的文件, 该文件用于后续编译INT8 模型的输入文件。
转成INT8对称量化cvimodel模型, 执行如下命令:
$ model_deploy.py \
    --MLIR yolov5s.MLIR \
    --quantize INT8 \
    --calibration_table yolov5s_cali_table \
    --chip cv183x \
    --test_input yolov5s_in_f32.npz \
    --test_reference yolov5s_top_outputs.npz \
    --tolerance 0.85,0.45 \
    --model yolov5s_cv183x_int8_sym.cvimodel
编译完成后, 会生成名为 ${model_name}_cv183x_int8_sym.cvimodel 的文件。
效果对比
onnx模型的执行方式如下, 得到 dog_onnx.jpg:
$ detect_yolov5.py \
    --input../image/dog.jpg \
    --model../yolov5s.onnx \
    --output dog_onnx.jpg
FP32 MLIR模型的执行方式如下,得到 dog_MLIR.jpg:
$ detect_yolov5.py \
    --input../image/dog.jpg \
    --model yolov5s.MLIR \
    --output dog_MLIR.jpg
BF16 cvimodel的执行方式如下, 得到 dog_bf16.jpg:
$ detect_yolov5.py \
    --input../image/dog.jpg \
    --model yolov5s_cv183x_bf16.cvimodel \
    --output dog_bf16.jpg
INT8 cvimodel的执行方式如下, 得到 dog_int8.jpg:
$ detect_yolov5.py \
    --input../image/dog.jpg \
    --model yolov5s_cv183x_int8_sym.cvimodel \
--output dog_int8.jpg
四张图片对比,如图 12-5所示,由于运行环境不同, 最终的效果与精度与图12-5会有些差异。
 
图12-5  yolov3_tiny ONNX执行效果示例
前面已经介绍了TPU-MLIR编译CV18xx系列芯片的ONNX模型的过程,caffe模型的转换过程可参考编译Caffe模型,只需要将对应的芯片名称换成实际的CV18xx芯片名称即可。
12.2.2 融合cvimodel模型文件
对于同一个模型,可以依据输入的batch size以及分辨率(不同的h与w)分别生成独立的cvimodel文件。不过为了节省外存与运存,可以选择将这些相关的cvimodel文件合并为一个cvimodel文件,共享其权重部分。具体步骤如下:
//第6章/model_transform_cvimodel.py
步骤0:生成batch 1的cvimodel
新建workspace目录,通过model_transform.py将yolov5s转换成MLIR fp32模型。
注意:
1.需要合并的cvimodel使用同一个workspace目录,并且不要与不需要合并的cvimodel 共用一个workspace;
2.步骤0、步骤1中 –merge_weight是必需选项。
$ model_transform.py \
    --model_name yolov5s \
    --model_def../yolov5s.onnx \
    --input_shapes [[1,3,640,640]] \
    --mean 0.0,0.0,0.0 \
    --缩放 0.0039216,0.0039216,0.0039216 \
    --keep_aspect_ratio \
    --pixel_format rgb \
    --output_names 350,498,646 \
    --test_input../image/dog.jpg \
    --test_result yolov5s_top_outputs.npz \
    --MLIR yolov5s_bs1.MLIR
使用前述生成的yolov5s_cali_table;如果没有,则通过run_calibration.py工具对yolov5s.MLIR进行量化校验获得校准表文件。然后将模型量化并生成cvimodel:
# 加上 --merge_weight参数
 $ model_deploy.py \
     --MLIR yolov5s_bs1.MLIR \
     --quantize INT8 \
     --calibration_table yolov5s_cali_table \
     --chip cv183x \
     --test_input yolov5s_in_f32.npz \
     --test_reference yolov5s_top_outputs.npz \
     --tolerance 0.85,0.45 \
     --merge_weight \
     --model yolov5s_cv183x_int8_sym_bs1.cvimodel
步骤1:生成batch 2的cvimodel
同步骤0,在同一个workspace中生成batch为2的MLIR fp32文件:
$ model_transform.py \
    --model_name yolov5s \
    --model_def../yolov5s.onnx \
    --input_shapes [[2,3,640,640]] \
    --mean 0.0,0.0,0.0 \
    --缩放 0.0039216,0.0039216,0.0039216 \
    --keep_aspect_ratio \
    --pixel_format rgb \
    --output_names 350,498,646 \
    --test_input../image/dog.jpg \
    --test_result yolov5s_top_outputs.npz \
    --MLIR yolov5s_bs2.MLIR
# 加上 --merge_weight参数
 $ model_deploy.py \
     --MLIR yolov5s_bs2.MLIR \
     --quantize INT8 \
     --calibration_table yolov5s_cali_table \
     --chip cv183x \
     --test_input yolov5s_in_f32.npz \
     --test_reference yolov5s_top_outputs.npz \
     --tolerance 0.85,0.45 \
     --merge_weight \
     --model yolov5s_cv183x_int8_sym_bs2.cvimodel
步骤2:合并batch 1与batch 2的cvimodel
使用model_tool合并两个cvimodel文件:
model_tool \
  --combine \
    yolov5s_cv183x_int8_sym_bs1.cvimodel \
    yolov5s_cv183x_int8_sym_bs2.cvimodel \
    -o yolov5s_cv183x_int8_sym_bs1_bs2.cvimodel
步骤3:runtime接口调用cvimodel
可以通过以下命令查看bs1与bs2指令的程序id:
model_tool --info yolov5s_cv183x_int8_sym_bs1_bs2.cvimodel
在运行时可以通过如下方式去运行不同的batch命令:
CVI_MODEL_HANDEL bs1_handle;
CVI_RC ret = CVI_NN_RegisterModel(yolov5s_cv183x_int8_sym_bs1_bs2.cvimodel, &bs1_handle);
assert(ret == CVI_RC_SUCCESS);
// 选择bs1的程序id
CVI_NN_SetConfig(bs1_handle, OPTION_PROGRAM_INDEX, 0);
CVI_NN_Get输入输出tensors(bs1_handle,...);
....
 
CVI_MODEL_HANDLE bs2_handle;
// 复用已加载的模型
CVI_RC ret = CVI_NN_CloneModel(bs1_handle, &bs2_handle);
assert(ret == CVI_RC_SUCCESS);
// 选择bs2的程序id
CVI_NN_SetConfig(bs2_handle, OPTION_PROGRAM_INDEX, 1);
CVI_NN_Getinputoutputtensors(bs2_handle,...);
...
 
// 最后销毁bs1_handle, bs2_handel
CVI_NN_CleanupModel(bs1_handle);
CVI_NN_CleanupModel(bs2_handle);
12.2.3 综述:融合过程
使用上面命令,不论是相同模型还是不同模型,均可以进行融合。融合的原理是:模型生成过程中,会叠加前面模型的权重(如果相同则共用)。
主要步骤在于:
1)用model_deploy.py生成模型时,加上–merge_weight参数;
2)要融合的模型的生成目录必须是同一个,且在融合模型前不要清理任何中间文件(叠加前面模型权重通过中间文件_weight_map.csv实现);
3)用model_tool –combine 将多个cvimodel融合。
1.编译与运行运行时示例
首先介绍EVB如何运行sample应用程序,然后介绍如何交叉编译sample应用程序,最后介绍docker仿真编译与运行sample。具体包括4个示例: * Sample-1: classifier (mobilenet_v2)
1)Sample-2: classifier_bf16 (mobilenet_v2);
2)Sample-3: 分类器融合预处理 (mobilenet_v2);
3)Sample-4: 分类器多批 (mobilenet_v2);
4)在EVB运行release提供的示例预编译程序。
将根据chip类型选择所需文件加载至EVB的文件系统,在EVB上的linux控制台执行,以cv183x为例:
解压示例使用的模型文件(以cvimodel格式交付),并解压TPU_SDK,并进入示例目录,执行测试过程,命令如下:
//第6章/cvimodel_samples.py
#env
tar zxf cvimodel_samples_cv183x.tar.gz
export MODEL_PATH=$PWD/cvimodel_samples
tar zxf cvitek_tpu_sdk_cv183x.tar.gz
export TPU_ROOT=$PWD/cvitek_tpu_sdk
cd cvitek_tpu_sdk && source./envs_tpu_sdk.sh
# get cvimodel info
cd samples
./bin/cvi_sample_model_info $MODEL_PATH/mobilenet_v2.cvimodel
 
####################################
# sample-1: 分类器
###################################
./bin/cvi_sample_classifier \
    $MODEL_PATH/mobilenet_v2.cvimodel \
   ./data/cat.jpg \
   ./data/synset_words.txt
 
# TOP_K[5]:
#  0.326172, idx 282, n02123159 tiger cat
#  0.326172, idx 285, n02124075 Egyptian cat
#  0.099609, idx 281, n02123045 tabby, tabby cat
#  0.071777, idx 287, n02127052 lynx, catamount
#  0.041504, idx 331, n02326432 hare
 
####################################
# sample-2: classifier_bf16
###################################
./bin/cvi_sample_classifier_bf16 \
    $MODEL_PATH/mobilenet_v2_bf16.cvimodel \
   ./data/cat.jpg \
   ./data/synset_words.txt
 
# TOP_K[5]:
#  0.314453, idx 285, n02124075 Egyptian cat
#  0.040039, idx 331, n02326432 hare
#  0.018677, idx 330, n02325366 wood rabbit, cottontail, cottontail rabbit
#  0.010986, idx 463, n02909870 bucket, pail
#  0.010986, idx 852, n04409515 tennis ball
 
 
############################################
# sample-3: 分类器融合预处理
############################################
./bin/cvi_sample_classifier_fused_preprocess \
    $MODEL_PATH/mobilenet_v2_fused_preprocess.cvimodel \
   ./data/cat.jpg \
   ./data/synset_words.txt
 
# TOP_K[5]:
#  0.326172, idx 282, n02123159 tiger cat
#  0.326172, idx 285, n02124075 Egyptian cat
#  0.099609, idx 281, n02123045 tabby, tabby cat
#  0.071777, idx 287, n02127052 lynx, catamount
#  0.041504, idx 331, n02326432 hare
 
############################################
# sample-4: 分类器多批
############################################
./bin/cvi_sample_classifier_multi_batch \
    $MODEL_PATH/mobilenet_v2_bs1_bs4.cvimodel \
   ./data/cat.jpg \
   ./data/synset_words.txt
 
# TOP_K[5]:
#  0.326172, idx 282, n02123159 tiger cat
#  0.326172, idx 285, n02124075 Egyptian cat
#  0.099609, idx 281, n02123045 tabby, tabby cat
#  0.071777, idx 287, n02127052 lynx, catamount
#  0.041504, idx 331, n02326432 hare
同时提供脚本作为参考,执行效果与直接运行相同,如下:
./run_classifier.sh
./run_classifier_bf16.sh
./run_classifier_fused_preprocess.sh
./run_classifier_multi_batch.sh
在cvitek_tpu_sdk/samples/samples_extra目录下有更多的示例,可供参考:
./bin/cvi_sample_detector_yolo_v3_fused_preprocess \
    $MODEL_PATH/yolo_v3_416_fused_preprocess_with_detection.cvimodel \
   ./data/dog.jpg \
    yolo_v3_out.jpg
 
./bin/cvi_sample_detector_yolo_v5_fused_preprocess \
    $MODEL_PATH/yolov5s_fused_preprocess.cvimodel \
   ./data/dog.jpg \
    yolo_v5_out.jpg
 
./bin/cvi_sample_detector_yolox_s \
    $MODEL_PATH/yolox_s.cvimodel \
   ./data/dog.jpg \
    yolox_s_out.jpg
 
./bin/cvi_sample_alphapose_fused_preprocess \
    $MODEL_PATH/yolo_v3_416_fused_preprocess_with_detection.cvimodel \
    $MODEL_PATH/alphapose_fused_preprocess.cvimodel \
   ./data/pose_demo_2.jpg \
    alphapose_out.jpg
 
./bin/cvi_sample_fd_fr_fused_preprocess \
    $MODEL_PATH/retinaface_mnet25_600_fused_preprocess_with_detection.cvimodel \
    $MODEL_PATH/arcface_res50_fused_preprocess.cvimodel \
   ./data/obama1.jpg \
   ./data/obama2.jpg
2.交叉编译示例程序
发布包有示例的源代码,按照方法在Docker环境下交叉编译示例程序,然后在evb上运行,命令如下:
//第6章/cvitek_tpu_sdk.py
需要如下文件:
1)cvitek_tpu_sdk_[cv182x|cv182x_uclibc|cv183x|cv181x_glibc32|cv181x_musl_riscv64_rvv|cv180x_musl_riscv64_rvv]].tar.gz
2)cvitek_tpu_samples.tar.gz
aarch 64位 (如cv183x aarch64位平台)
TPU sdk准备:
tar zxf host-tools.tar.gz
tar zxf cvitek_tpu_sdk_cv183x.tar.gz
export PATH=$PWD/host-tools/gcc/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin:$PATH
export TPU_SDK_PATH=$PWD/cvitek_tpu_sdk
cd cvitek_tpu_sdk && source./envs_tpu_sdk.sh && cd..
编译示例,安装至install_samples目录:
tar zxf cvitek_tpu_samples.tar.gz
cd cvitek_tpu_samples
mkdir build_soc
cd build_soc
cmake -G Ninja \
    -DCMAKE_BUILD_TYPE=RELEASE \
    -DCMAKE_C_FLAGS_RELEASE=-O3 \
    -DCMAKE_CXX_FLAGS_RELEASE=-O3 \
    -DCMAKE_TOOLCHAIN_FILE=$TPU_SDK_PATH/cmake/toolchain-aarch64-linux.cmake \
    -DTPU_SDK_PATH=$TPU_SDK_PATH \
    -DOPENCV_PATH=$TPU_SDK_PATH/opencv \
    -DCMAKE_INSTALL_PREFIX=../install_samples \
   ..
cmake --build. --target install
arm 32位 (如cv183x平台32位、cv182x平台)
TPU sdk准备:
tar zxf host-tools.tar.gz
tar zxf cvitek_tpu_sdk_cv182x.tar.gz
export TPU_SDK_PATH=$PWD/cvitek_tpu_sdk
export PATH=$PWD/host-tools/gcc/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin:$PATH
cd cvitek_tpu_sdk && source./envs_tpu_sdk.sh && cd..
如果docker版本低于1.7,则需要更新32位系统库(只需一次):
dpkg --add-architecture i386
apt-get update
apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
编译示例,安装至install_samples目录:
tar zxf cvitek_tpu_samples.tar.gz
cd cvitek_tpu_samples
mkdir build_soc
cd build_soc
cmake -G Ninja \
    -DCMAKE_BUILD_TYPE=RELEASE \
    -DCMAKE_C_FLAGS_RELEASE=-O3 \
    -DCMAKE_CXX_FLAGS_RELEASE=-O3 \
    -DCMAKE_TOOLCHAIN_FILE=$TPU_SDK_PATH/cmake/toolchain-linux-gnueabihf.cmake \
    -DTPU_SDK_PATH=$TPU_SDK_PATH \
    -DOPENCV_PATH=$TPU_SDK_PATH/opencv \
    -DCMAKE_INSTALL_PREFIX=../install_samples \
   ..
cmake --build. --target install
uclibc 32位平台 (cv182x uclibc平台)
TPU sdk准备:
tar zxf host-tools.tar.gz
tar zxf cvitek_tpu_sdk_cv182x_uclibc.tar.gz
export TPU_SDK_PATH=$PWD/cvitek_tpu_sdk
export PATH=$PWD/host-tools/gcc/arm-cvitek-linux-uclibcgnueabihf/bin:$PATH
cd cvitek_tpu_sdk && source./envs_tpu_sdk.sh && cd..
如果docker版本低于1.7,则需要更新32位系统库(只需一次):
dpkg --add-architecture i386
apt-get update
apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
编译示例,安装至install_samples目录:
tar zxf cvitek_tpu_samples.tar.gz
cd cvitek_tpu_samples
mkdir build_soc
cd build_soc
cmake -G Ninja \
    -DCMAKE_BUILD_TYPE=RELEASE \
    -DCMAKE_C_FLAGS_RELEASE=-O3 \
    -DCMAKE_CXX_FLAGS_RELEASE=-O3 \
    -DCMAKE_TOOLCHAIN_FILE=$TPU_SDK_PATH/cmake/toolchain-linux-uclibc.cmake \
    -DTPU_SDK_PATH=$TPU_SDK_PATH \
    -DOPENCV_PATH=$TPU_SDK_PATH/opencv \
    -DCMAKE_INSTALL_PREFIX=../install_samples \
   ..
cmake --build. --target install
riscv64位 musl平台 (如cv181x、cv180x riscv64位 musl平台)
TPU sdk准备:
tar zxf host-tools.tar.gz
tar zxf cvitek_tpu_sdk_cv181x_musl_riscv64_rvv.tar.gz
export TPU_SDK_PATH=$PWD/cvitek_tpu_sdk
export PATH=$PWD/host-tools/gcc/riscv64-linux-musl-x86_64/bin:$PATH
cd cvitek_tpu_sdk && source./envs_tpu_sdk.sh && cd..
编译示例,安装至install_samples目录:
tar zxf cvitek_tpu_samples.tar.gz
cd cvitek_tpu_samples
mkdir build_soc
cd build_soc
cmake -G Ninja \
    -DCMAKE_BUILD_TYPE=RELEASE \
    -DCMAKE_C_FLAGS_RELEASE=-O3 \
    -DCMAKE_CXX_FLAGS_RELEASE=-O3 \
    -DCMAKE_TOOLCHAIN_FILE=$TPU_SDK_PATH/cmake/toolchain-riscv64-linux-musl-x86_64.cmake \
    -DTPU_SDK_PATH=$TPU_SDK_PATH \
    -DOPENCV_PATH=$TPU_SDK_PATH/opencv \
    -DCMAKE_INSTALL_PREFIX=../install_samples \
   ..
cmake --build. --target install
riscv64位 glibc平台 (如cv181x、cv180x riscv64位glibc平台)
TPU sdk准备:
tar zxf host-tools.tar.gz
tar zxf cvitek_tpu_sdk_cv181x_glibc_riscv64.tar.gz
export TPU_SDK_PATH=$PWD/cvitek_tpu_sdk
export PATH=$PWD/host-tools/gcc/riscv64-linux-x86_64/bin:$PATH
cd cvitek_tpu_sdk && source./envs_tpu_sdk.sh && cd..
编译示例,安装至install_samples目录:
tar zxf cvitek_tpu_samples.tar.gz
cd cvitek_tpu_samples
mkdir build_soc
cd build_soc
cmake -G Ninja \
    -DCMAKE_BUILD_TYPE=RELEASE \
    -DCMAKE_C_FLAGS_RELEASE=-O3 \
    -DCMAKE_CXX_FLAGS_RELEASE=-O3 \
    -DCMAKE_TOOLCHAIN_FILE=$TPU_SDK_PATH/cmake/toolchain-riscv64-linux-x86_64.cmake \
    -DTPU_SDK_PATH=$TPU_SDK_PATH \
    -DOPENCV_PATH=$TPU_SDK_PATH/opencv \
    -DCMAKE_INSTALL_PREFIX=../install_samples \
   ..
cmake --build. --target install
docker环境仿真运行的示例程序,命令如下:
//第6章/cvimodel_samples.py
需要如下文件:
1)cvitek_MLIR_ubuntu-18.04.tar.gz
2)cvimodel_samples_[cv182x|cv183x|cv181x|cv180x].tar.gz
3)cvitek_tpu_samples.tar.gz
TPU sdk准备:
tar zxf cvitek_MLIR_ubuntu-18.04.tar.gz
source cvitek_MLIR/cvitek_envs.sh
编译示例,安装至install_samples目录:
tar zxf cvitek_tpu_samples.tar.gz
cd cvitek_tpu_samples
mkdir build_soc
cd build_soc
cmake -G Ninja \
   -DCMAKE_BUILD_TYPE=RELEASE \
   -DCMAKE_C_FLAGS_RELEASE=-O3 \
   -DCMAKE_CXX_FLAGS_RELEASE=-O3 \
   -DTPU_SDK_PATH=$MLIR_PATH/tpuc \
   -DCNPY_PATH=$MLIR_PATH/cnpy \
   -DOPENCV_PATH=$MLIR_PATH/opencv \
   -DCMAKE_INSTALL_PREFIX=../install_samples \
  ..
cmake --build. --target install
运行示例程序:
# envs
tar zxf cvimodel_samples_cv183x.tar.gz
export MODEL_PATH=$PWD/cvimodel_samples
source cvitek_MLIR/cvitek_envs.sh
 
# get cvimodel info
cd../install_samples
./bin/cvi_sample_model_info $MODEL_PATH/mobilenet_v2.cvimodel
其他示例运行命令参照EVB运行命令
BM168x测试指南
配置系统环境
如果是首次使用Docker, 那么请使用 开发环境配置 中的方法安装 并配置Docker。同时, 中会使用到 git-lfs, 如果首次使用 git-lfs 可执行下述命 令进行安装与配置(仅首次执行, 同时该配置是在用户自己系统中, 并非Docker 容器中):
$ curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
$ sudo apt-get install git-lfs
获取 model-zoo 模型 1
在 tpu-MLIR_xxxx.tar.gz (tpu-MLIR的发布包)的同级目录下, 使用以下命令克隆 model-zoo 工程:
$ git clone --depth=1 需要如下文件:
1)cvitek_MLIR_ubuntu-18.04.tar.gz
2)cvimodel_samples_[cv182x|cv183x|cv181x|cv180x].tar.gz
3)cvitek_tpu_samples.tar.gz
TPU sdk准备:
tar zxf cvitek_MLIR_ubuntu-18.04.tar.gz
source cvitek_MLIR/cvitek_envs.sh
编译示例,安装至install_samples目录:
tar zxf cvitek_tpu_samples.tar.gz
cd cvitek_tpu_samples
mkdir build_soc
cd build_soc
cmake -G Ninja \
   -DCMAKE_BUILD_TYPE=RELEASE \
   -DCMAKE_C_FLAGS_RELEASE=-O3 \
   -DCMAKE_CXX_FLAGS_RELEASE=-O3 \
   -DTPU_SDK_PATH=$MLIR_PATH/tpuc \
   -DCNPY_PATH=$MLIR_PATH/cnpy \
   -DOPENCV_PATH=$MLIR_PATH/opencv \
   -DCMAKE_INSTALL_PREFIX=../install_samples \
  ..
cmake --build. --target install
运行示例程序:
# envs
tar zxf cvimodel_samples_cv183x.tar.gz
export MODEL_PATH=$PWD/cvimodel_samples
source cvitek_MLIR/cvitek_envs.sh
 
# get cvimodel info
cd../install_samples
./bin/cvi_sample_model_info $MODEL_PATH/mobilenet_v2.cvimodel
其他示例运行命令参照EVB运行命令
BM168x测试指南
配置系统环境
如果是首次使用Docker, 那么请使用 开发环境配置 中的方法安装 并配置Docker。同时, 中会使用到 git-lfs, 如果首次使用 git-lfs 可执行下述命 令进行安装与配置(仅首次执行, 同时该配置是在用户自己系统中, 并非Docker 容器中):
$ curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
$ sudo apt-get install git-lfs
获取 model-zoo 模型 1
在 tpu-MLIR_xxxx.tar.gz (tpu-MLIR的发布包)的同级目录下, 使用以下命令克隆 model-zoo 工程:
$ git clone --depth=1 https://github.com/sophgo/model-zoo
$ cd model-zoo
$ git lfs pull --include *.onnx,*.jpg,*.JPEG --exclude=""
$ cd../
如果已经克隆过 model-zoo 可以执行以下命令同步模型到最新状态:
$ cd model-zoo
$ git pull
$ git lfs pull --include "*.onnx,*.jpg,*.JPEG" --exclude=""
$ cd../
此过程会从 GitHub 上下载大量数据。由于具体网络环境的差异, 此过程可能耗时较长。
如果获得了SOPHGO提供的 model-zoo 测试包, 可以执行以下操作创建并 设置好 model-zoo。完成此步骤后直接获取 tpu-perf 工具。
$ mkdir -p model-zoo
$ tar -xvf path/to/model-zoo_.tar.bz2 --strip-components=1 -C model-zoo
https://github.com/sophgo/model-zoo
$ cd model-zoo
$ git lfs pull --include *.onnx,*.jpg,*.JPEG --exclude=""
$ cd../
如果已经克隆过 model-zoo 可以执行以下命令同步模型到最新状态:
$ cd model-zoo
$ git pull
$ git lfs pull --include "*.onnx,*.jpg,*.JPEG" --exclude=""
$ cd../
此过程会从 GitHub 上下载大量数据。由于具体网络环境的差异, 此过程可能耗时较长。
如果获得了SOPHGO提供的 model-zoo 测试包, 可以执行以下操作创建并 设置好 model-zoo。完成此步骤后直接获取 tpu-perf 工具。
$ mkdir -p model-zoo
$ tar -xvf path/to/model-zoo_.tar.bz2 --strip-components=1 -C model-zoo
3.获取 tpu-perf 工具
从 https://github.com/sophgo/tpu-perf/releases 地址下载最新的 tpu-perf wheel安装包。例如: tpu_perf-x.x.x-py3-none-manylinux2014_x86_64.whl。并将 tpu-perf 包放置到与 model-zoo 同一级目录下。此时的目录结构应该为如下形式:
├── tpu_perf-x.x.x-py3-none-manylinux2014_x86_64.whl
├── tpu-MLIR_xxxx.tar.gz
└── model-zoo
12.2.4 测试流程
1.解压SDK并创建Docker容器
在 tpu-MLIR_xxxx.tar.gz 目录下(注意, tpu-MLIR_xxxx.tar.gz 与 model-zoo 需要在同一级目录), 执行命令如下:
//第6章/tpu-MLIR_xxxx.sh
$ tar zxf tpu-MLIR_xxxx.tar.gz
$ docker pull sophgo/tpuc_dev:latest
$ docker run --rm --name myname -v $PWD:/workspace -it sophgo/tpuc_dev:latest
运行命令后会处于Docker的容器中。
设置环境变量并安装 tpu-perf
使用以下命令完成设置运行测试所需的环境变量:
$ cd tpu-MLIR_xxxx
$ source envsetup.sh
该过程结束后不会有任何提示。之后使用以下命令安装 tpu-perf:
$ pip3 install../tpu_perf-x.x.x-py3-none-manylinux2014_x86_64.whl
运行测试
编译模型
model-zoo 的相关 confg.yaml 配置了SDK的测试内容。例如: resnet18的 配置文件为 model-zoo/vision/classification/resnet18-v2/config.yaml。
执行以下命令, 运行全部测试样例:
$ cd../model-zoo
$ python3 -m tpu_perf.build --MLIR -l full_cases.txt
此时会编译以下模型:
* efficientnet-lite4
* mobilenet_v2
* resnet18
* resnet50_v2
* shufflenet_v2
* squeezenet1.0
* vgg16
* yolov5s
命令正常结束后, 会看到新生成的输出文件夹(测试输出内容都在该文件夹中)。 修改 输出文件夹的属性, 以保证其可以被Docker外系统访问。
$ chmod -R a+rw output
2.测试模型性能,配置SOC设备
注意: 如果设备是 PCIE 板卡, 可以直接跳过该节内容。
性能测试只依赖于 libsophon 运行环境, 所以在工具链编译环境编译完的模型连同 model-zoo 整个打包, 就可以在 SOC 环境使用 tpu_perf 进行性能与精度测试。 但是, SOC设备上存储有限, 完整的 model-zoo 与编译输出内容可能无法完整拷贝到 SOC 中。这里介绍一种通过 linux nfs 远程文件系统挂载来实现在 SOC 设备上运行测试的方法,命令如下:
//第6章/chmod_rw_output.sh
$ chmod -R a+rw output
首先, 在工具链环境服务器host 系统安装 nfs 服务:
$ sudo apt install nfs-kernel-server
在 /etc/exports 中添加以下内容(配置共享目录):
/the/absolute/path/of/model-zoo *(rw,sync,no_subtree_check,no_root_squash)
其中 * 表示所有人都可以访问该共享目录, 也可以配置成特定网段或 IP 可访问, 如:
/the/absolute/path/of/model-zoo 192.168.43.0/24(rw,sync,no_subtree_check,no_root_squash)
然后执行如下命令使配置生效:
$ sudo exportfs -a
$ sudo systemctl restart nfs-kernel-server
另外, 需要为 dataset 目录下的图片添加读取权限:
chmod -R +r path/to/model-zoo/dataset
在 SOC 设备上安装客户端并挂载该共享目录:
$ mkdir model-zoo
$ sudo apt-get install -y nfs-common
$ sudo mount -t nfs:/path/to/model-zoo./model-zoo
这样便可以在 SOC 环境访问测试目录。SOC 测试其余的操作与 PCIE 基本一致, 请参考下 文进行操作; 运行环境命令执行位置的差别, 已经在执行处添加说明。
运行测试
运行测试需要在 Docker 外面的环境(此处假设已经安装并配置好了1684X设备与 驱动)中进行, 可以退出 Docker 环境:
$ exit
1.  PCIE 板卡下运行以下命令, 测试生成的 bmodel 性能。
$ pip3 install./tpu_perf-*-py3-none-manylinux2014_x86_64.whl
$ cd model-zoo
$ python3 -m tpu_perf.run --MLIR -l full_cases.txt
注意:如果主机上安装了多块SOPHGO的加速卡,可以在使用 tpu_perf 时,通过添加 --devices id 来指定 tpu_perf 的运行设备。如:
$ python3 -m tpu_perf.run --devices 2 --MLIR -l full_cases.txt
1.  SOC 设备使用以下步骤, 测试生成的 bmodel 性能。
从 https://github.com/sophgo/tpu-perf/releases 地址下载最新的 tpu-perf tpu_perf-x.x.x-py3-none-manylinux2014_aarch64.whl 文件到SOC设备上并执行 以下操作:
$ pip3 install./tpu_perf-x.x.x-py3-none-manylinux2014_aarch64.whl
$ cd model-zoo
$ python3 -m tpu_perf.run --MLIR -l full_cases.txt
运行结束后, 性能数据在output/stats.csv 中可以获得。该文件中记录了相关模型的运行时间、计算资源利用率与带宽利用率。
 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/12468125.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

centos7安装python3.12.3(最新)

一.安装环境: Linux系统:centos7,可以正常访问互联网。 python版本:3.12.3,建议网工直接就是安装python3的最新版本,毕竟python2和我们网工更不相关了。 环境最基本的就这些了 二.安装步骤 1.安装python3: 不多说,直接上安装过程~ #只是将python3.12.3的安装包下载到 /…

Deep Hello world!

目录1. #include <stdio.h>2.int 整形数据类型3.main 函数4.printf 函数5.return 函数6.”{}”与“;” “Hellow world!"是初学者的第一份代码,可以说所学万物代码之基础。下面看一下代码是如何实现的:代码虽然简洁,但是包含了许多C语言的知识,我们从上往下看有…

20220405【黑历史】M1 Mac使用PD虚拟机配合VSC代替Keil烧录MM32单片机

0.前言因为智能车竞赛而接触到了MM32F32G9P这款单片机。而由于我很喜欢macOS系统,加上我同时喜欢剪视频,因此买了一个arm芯片的MacBook Pro,但这就限制了我没办法用双系统运行Windows系统,只能转而使用虚拟机。使用Mac烧录stm32的教程很多,但是很少有mm32的教程。理论上这…

OOP第一次博客作业

一. 前言 在过去三周里每周都有一次PTA大作业,每次的内容都是在前一次的内容上更加复杂,也更完善。这几次作业考察的不只是基础的Java语法,还有正则表达式,动态列表等,更注重语句之间的逻辑性。从前几次简单的程序要求一下跳到这么困难的题,让人有点难以适应。特别是不定…

OOP第一阶段题集总结

一.前言知识点:数组,字符串的使用,链表,hashmap,泛型的使用,正则表达式的使用,类的设计,类与类之间的关系,单一职责。 题量:题目数量为5+4+3,数量适中,其中都是前几题较简单,最后一题较为复杂,且每一次都是在前一次的基础上进行迭代。 难度:前几题基础简单,最后…

科研软件

【专业软件】科研软件看这里,方便你我他 封面目录页 1. 科研专业软件1.1. 数值模拟1.1.1. 有限元 1.1.2. 离散元1.2. 顶级图像分析软件2. 实用小工具2.1. GIF制作2.1.1. ScreenToGif2.2. 文字识别2.2.1. 公式识别2.3. 网络限制版资源获取2.3.1. yotub…