7.8. BM1684(X)_to_BM1688(CV186AH)兼容性文档
该文档面向有一定SOPHONSDK使用经验的用户,它还需丰富和完善,如果您发现了新的问题或有改进建议,可以反馈给我们的工作人员。
7.8.1. 获取BM1688/CV186AH SOPHONSDK
BM1688/CV186AH的SOPHONSDK与BM1684/BM1684X的SOPHONSDK不是同一套,所以需要另外从官网获取。下载后使用工具解压,可以得到各个模块的安装包、示例程序,SDK目录结构如下:
文件夹名 |
备注 |
---|---|
sophon-img |
SoC模式安装包等 |
sophon_media |
支持SOPHON设备硬件加速的多媒体库 |
tpu-mlir |
TPU编译器工具链 |
tpu-perf |
模型性能和精度验证工具包 |
sophon-stream |
基于pipeline的高性能推理框架 |
sophon-demo |
针对单模型或者场景的综合例程 |
sophon-sail |
对底层接口进行C++/Python API封装的接口库 |
isp-tools |
ISP各个模块的参数调节工具 |
doc |
各个模块的文档资料合集 |
7.8.2. 准备BM1688/CV186AH的bmodel
重新编译能在BM1688/CV186AH上运行的bmodel,需要使用能够支持BM1688/CV186AH的tpu-mlir。
一般来说,有以下几个步骤:
准备一台x86 ubuntu,相应的规格参数,取决于需要编译的模型大小,建议运行内存32GB以上,这样足够编译绝大多数模型。
运行如下命令,搭建tpu-mlir环境:
# 拉取latest版本docker,目前对应tpuc_dev:v3.2,如果您的环境已经有这个image了,也需要重新执行以下命令。 docker pull sophgo/tpuc_dev:latest # 这里将本级目录映射到docker内的/workspace目录,用户需要根据实际情况将demo的目录映射到docker里面 # myname只是举个名字的例子, 请指定成自己想要的容器的名字 docker run --privileged --name myname -v $PWD:/workspace -it sophgo/tpuc_dev:latest # 此时已经进入docker,并在/workspace目录下 # 通过pip下载tpu_mlir,如果下不下来,可以使用清华源加速。 pip install tpu_mlir # TPU-MLIR在对不同框架模型处理时所需的依赖不同。对于onnx或torch生成的模型文件,使用类似下面命令安装额外的依赖环境: pip install tpu_mlir[onnx] pip install tpu_mlir[torch] # 目前支持五种配置: onnx, torch, tensorflow, caffe, paddle。可使用一条命令安装多个配置,也可直接安装全部依赖环境: pip install tpu_mlir[onnx,torch] pip install tpu_mlir[all]
编译模型:
只要将以前的编译命令或脚本中model_deploy.py部分的
--processor
,参数值更改成bm1688/cv186x,其他的部分都不用改动,运行之后就可以获取能在BM1688/CV186AH上运行的bmodel。编译BM1688双核模型:
BM1688由两个相同的核组成,支持一个模型的数据切分到两个核上面跑,tpu-mlir model_deploy.py为BM1688新增了
--num_core
参数,如果您想要一个模型跑两个核,可以在model_deploy.py中新增--num_core 2
参数,这样就编译出来的模型,会由两个核来执行。量化注意事项:
以前的calibration_table和qtable均是可以复用的,如果在mlir编译bmodel的过程中出现类似算子不支持的报错,或者量化出来的模型精度不好,再重新生成calibration_table或qtable。
7.8.3. 准备编译依赖的SDK
如果您使用C++编程,您仍然需要获取sophon-img目录下的libsophon_soc_${x.y.z}/_aarch64.tar.gz和sophon_media目录下的sophon-media-soc_${x.y.z}/_aarch64.tar.gz发布包,作为交叉编译依赖的头文件和库文件。
如果以前有手动链接 bmion/bmjpulite/bmjpuapi/bmvpulite/bmvpuapi/bmvideo/bmvppapi 等库,可以直接去掉,这些库其实并没有暴露接口给用户,它们是供底层调用的。
和BM1684/BM1684X有一点不同的是,目前sophon_media中提供的库还依赖libisp模块,如果您使用BM1688/CV186AH的GeminiSDK1.3以上版本,您还需要做这些操作:
从sdk中获取sophon-img/bsp-debs/目录下的sophon-soc-libisp_${x.y.z}_arm64.deb,然后运行如下命令:
dpkg -x sophon-soc-libisp_${x.y.z}_arm64.deb sophon-libisp
cp -rf sophon-libisp/opt/sophon/sophon-soc-libisp_${x.y.z}/lib ${soc-sdk} #将libisp的库添加到已有的依赖库中。
如果您使用Python编程,那只需要重新编译sophon-sail的.whl安装包,编译流程与之前相同,参考sophon-sail开发指南即可。BM1688 SoC上自带libsophon和sophon_media的runtime。
7.8.4. SDK版本≥1.7 兼容性适配
BM1688/CV186AH SOPHONSDK 1.7及以上版本,对兼容性问题做了进一步的优化,只需要保证您的代码引入了以下头文件即可。
#include <bmcv_api.h>
7.8.4.1. 头文件改动
bmcv_api.h已废弃,兼容性解决办法如下:
#if !(BMCV_VERSION_MAJOR > 1) #include <bmcv_api.h> #endif
7.8.4.2. bmcv改动
函数参数变为指针:
DECL_EXPORT bm_status_t bm_image_destroy(bm_image image)
变为
DECL_EXPORT bm_status_t bm_image_destroy(bm_image *image)
兼容性解决办法如下:
在公共头文件中添加如下代码:
#if BMCV_VERSION_MAJOR > 1 static inline bm_status_t bm_image_destroy(bm_image& image){ return bm_image_destroy(&image); } #endif
函数名称变化:
bm_image_dev_mem_alloc
变为
bm_image_alloc_dev_mem
兼容性解决办法:
在公共头文件中封装一个相同功能的旧接口。
接口名称修正:
bm_image_dettach_contiguous_mem
修正为
bm_image_detach_contiguous_mem
兼容性解决办法:
在公共头文件中封装一个相同功能的旧接口。
结构体名称修正
bmcv_padding_atrr_t
修正为
bmcv_padding_attr_t
兼容性解决办法:
在公共头文件中添加
typedef bmcv_padding_attr_t bmcv_padding_atrr_t;
。
接口废弃:
bmcv_image_crop
兼容性解决办法:
使用bmcv_image_vpp_convert来代替。
或者在公共头文件使用bmcv_image_vpp_convert封装一个bmcv_image_crop接口。
数据类型废弃:
DATA_TYPE_EXT_4N_BYTE_SIGNED DATA_TYPE_EXT_4N_BYTE
兼容性解决办法:
4N数据类型在以前的SDK中也很少使用,不建议再使用4N数据类型,改用1N数据类型。
内存布局改动导致的接口功能改动:
bm_image_alloc_dev_mem(heap_id = 2) bm_image_alloc_dev_mem_heap_mask(heap_mask = 1 << 2) bm_image_alloc_contiguous_mem_heap_mask(heap_mask = 1 << 2)
BM1688/CV186AH上只有两个heap,原来放在heap2的内存需要挪到heap1,否则分配失败。如上接口的heap_id/heap_mask参数需要改为:
bm_image_alloc_dev_mem(heap_id = 1) bm_image_alloc_dev_mem_heap_mask(heap_mask = 1 << 1) bm_image_alloc_contiguous_mem_heap_mask(heap_mask = 1 << 1)
暂未支持的接口:
bmcv_base64_enc() bmcv_base64_dec() bmcv_faiss_indexflatIP() bmcv_nms() bmcv_nms_ext() bmcv_fft_1d_create_plan() bmcv_fft_2d_create_plan() bmcv_fft_execute() bmcv_fft_execute_real_input() bmcv_fft_destroy_plan()
7.8.4.3. ffmpeg改动
ffmpeg版本从4.1升级到了6.0,由此引入了一些ffmpeg本身的改动,如下:
接口废弃:
av_register_all
兼容性解决办法:
去掉
或者封装一个av_register_all。
avcodec_decode_video2 avcodec_encode_video2
兼容性解决办法:
按照ffmpeg文档,改成avcodec_send_packet和avcodec_receive_frame的形式。
可以自己封装一个avcodec_decode_video2,参考https://github.com/sophgo/sophon-demo/blob/release/include/ff_decode.hpp
可以自己封装一个avcodec_encode_video2,参考sophon-sail src/internal.h
结构体或函数类型变为const:
struct AVOutputFormat *oformat; AVInputFormat* av_find_input_format AVCodec* avcodec_find_decoder AVOutputFormat* av_guess_format AVCodec* avcodec_find_decoder_by_name AVCodec* avcodec_find_decoder_by_name
变为
const struct AVOutputFormat *oformat const AVInputFormat* av_find_input_format const AVCodec* avcodec_find_decoder const AVOutputFormat* av_guess_format const AVCodec* avcodec_find_decoder_by_name const AVCodec* avcodec_find_decoder_by_name
兼容性解决办法:
使用const_cast去掉const修饰符。
结构体成员变量变化:
AVStream->codec
变为
AVStream->codecpar
兼容性解决办法:
avcodec_parameters_to_context重新获取上下文,avcodec_parameters_from_context把上下文内容重新拷贝到流中。
7.8.4.4. bmlib改动
新增接口:
DECL_EXPORT bm_status_t bm_thread_sync_from_core(bm_handle_t handle, int core_id);
功能描述:
可以指定只sync某个核,在每个核各跑一个模型时会用到。
内存布局改动导致的接口功能改动:
bm_malloc_device_byte_heap(heap_id = 2) bm_malloc_device_byte_heap_mask(heap_mask = 1 << 2)
BM1688/CV186AH上只有两个heap,原来放在heap2的内存需要挪到heap1,否则分配失败。如上接口的heap_id/heap_mask参数需要改为:
bm_malloc_device_byte_heap(heap_id = 1) bm_malloc_device_byte_heap_mask(heap_mask = 1 << 1)
7.8.4.5. bmrt改动
新增接口:
DECL_EXPORT bool bmrt_launch_tensor_multi_cores(void *p_bmrt, const char *net_name, const bm_tensor_t input_tensors[], int input_num, bm_tensor_t output_tensors[], int output_num, bool user_mem, bool user_stmode, const int *core_list, int core_num);
功能描述:
该接口可以将单核模型指定在不同的核上运行,具体请查看SOPHONSDK的bmruntime接口文档或源码。
7.8.5. 准备BM1688/CV186AH运行环境
BM1688/CV186AH的刷机步骤和BM1684/BM1684X相同,具体可以看相关的产品使用手册,在 获取BM1688/CV186AH SOPHONSDK 章节下载的SDK中,sophon-img/sdcard.tgz文件就是刷机包。
准备好运行环境之后,就可以将编译好的程序拷贝到BM1688/CV186AH SoC上执行了。
7.8.6. 其他注意事项
bmrt、bmcv相关的操作,最好把各自分配的内存隔离开,bmrt需要用到的内存放在heap0(也就是npu heap),bmcv需要用到的内存则放在heap1(也就是vpp heap)。
由于BM1688的内存减小,ddr是全interleave的,没有带宽分配问题,因此不再预留vpu heap,多媒体模块共用vpp heap。
bm1688的sdk目前只把ddr划分成npu、vpp两个heap,查看方法改为:
sudo cat /sys/kernel/debug/ion/cvi_vpp_heap_dump/summary sudo cat /sys/kernel/debug/ion/cvi_npu_heap_dump/summary
内存布局修改工具:SoC模式内存修改工具
可以兼容BM1688/CV186AH Gemini v1.5以上SDK,vpu heap需要设置为0。