海思AI芯片(Hi3519A/3559A)方案学习(十八)如何将sample sdk代码重构并编译成动态链接库

前言

前面的博客我们已经分析了yolov3相关sample代码。但这毕竟是参考代码,不能直接拿来在自己项目中使用。本文就主要谈如何将sample中的yolov3相关代码提取出来,重新组织,并编译成so库,提供api给应用软件调用。

代码重构

sample代码除了有yolov3相关代码外,还有别的模型如RFCN等推理。当然,还有很多的代码是这些模型共用的。熟读这些代码后,我将yolov3相关的代码分成了三个c文件:

nnie_ai.c:  主要提供public API接口给应用软件调用,比如 nnie_init, nnie_load_model以及nnie_forward。

nnie_driver.c: 主要是和HI_XXX底层接口打交道的代码层。它的public接口将被nnie_ai.c调用。

nnie_yolo3_sw.c: 该文件是专门针对yolo3模型的推理结果进行parse来获得最终的目标检测结果值。因为nnie不识别yolo层,所以这段分析代码需要跑在cpu上,这也是为什么取名sw的原因。它的public接口也是会被nnie_ai.c调用。

编译成动态库

在编译成一个能正常运行的so库过程中,会遇到很多错误,如下所示。

1)未定义错误,比如error: unkown type name 'SAMPLE_SVP_NNIE_YOLOV3_SOFTWARE_PARAM_S'

这类错误往往是 缺少头文件。解决很简单,缺啥就从sample sdk里面拷过来。

2)warning:implicit declaration of function 'usleep'

解决办法就是 添加头文件  #include

3)warning: implicit declaration of function 'exp'

办法: #include

将动态库和测试代码一起编译连接成可执行文件时,会遇到下面链接问题

4)undefined reference to 'HI_MPI_SYS_Init'

: 要链接 libmpi.a。 可以使用readelf -s libmpi.a | grep HI_MPI_SYS_Init或nm命令来查询该接口是否在该库里面提供

5) undefined reference to 'exp' or 'memcpy_s'等

:要链接math,libsecure.a等库。

6)undefined reference to 'dlopen' or 'dlerror' or 'dlclose'

: 编译参数里面添加 -ldl,表示支持显示加载动态库。

速度优化

7)指定硬件浮点单元来加速cpu的浮点数运算速度

添加: -mfloat-abi=softfp -mfpu=neon-vfpv4

结论

最后的编译成可运行的动态库命令如下所示供大家参考。

在ubuntu上编译测试代码main成可执行文件时,可以通过-L来指定libnnie_ai.so所在路径,但在板子上运行时,由于平台环境差距较大,往往导致加载so文件失败。所以需要通过更新LD_LIBARARY_PATH或ld.so.conf或拷贝到系统目录/lib 或 /usr/lib来进行解决,具体可以参考另外一篇博文:Linux下头文件以及库 编译链接运行时的搜寻路径顺序

 

 

你可能感兴趣的:(嵌入式AI)