【STM32开发笔记】移植AI框架TensorFlow到STM32单片机【DSP指令加速篇】

【STM32开发笔记】移植AI框架TensorFlow到STM32单片机【DSP指令加速篇】

    • 一、前文回顾
    • 二、CMSIS-NN简介
      • 2.1 为什么介绍CMSIS-NN?
      • 2.2 CMSIS-NN是什么?
      • 2.3 CMSIS-NN核心特性
      • 2.4 CMSIS-NN算子支持
    • 三、TFLM+CMSIS-NN集成
      • 3.1 包含TFLM的STM32项目
      • 3.2 理解TFLM中CMSIS-NN相关构建规则
      • 3.3 理解TFLM中CMSIS-NN相关算子实现
      • 3.4 集成CMSIS-NN方式1——作为TFLM的一部分
      • 3.5 集成CMSIS-NN方式2——作为独立的三方库
    • 四、TFLM+CMSIS-NN测试
      • 4.1 编译源代码
      • 4.2 下载Boot代码
      • 4.3 下载Appli代码
      • 4.4 运行TFLM基准测试
    • 五、问题解决
      • 5.1 specialize_files.py 输入不支持CMake列表参数问题
      • 5.2 specialize_files.py 输出的路径分隔符不一致问题
      • 5.3 specialize_files.py 输出和CMake列表格式不一致问题
      • 5.4 specialize_files.py 输出的最后一个文件无法找到
    • 六、项目源码
    • 七、参考链接

本文介绍了如何通过移植CMSIS-NN库并调整TensorFlow Lite for Microcontrollers (TFLM) 的构建配置,实现在STM32微控制器上利用DSP指令集加速TensorFlow Lite模型的推理过程。通过这一方法,我们能够有效地提升基于ARM Cortex-M系列MCU上运行深度学习模型的性能。文章首先介绍了CMSIS-NN库的基本概念及其在神经网络加速中的作用,随后详细阐述了移植库到STM32平台的步骤。接着,文章深入讲解了如何修改TFLM的构建规则,实现调用CMSIS-NN库实现TensorFlow算子。最后,通过实验验证了该方法在提高模型推理速度方面的显著效果,使用CMSIS-NN实现DSP加速后的人脸检测模型推理速度接近原来的3.5倍。

本系列博文目录:

  1. 【STM32开发笔记】移植AI框架TensorFlow到STM32单片机【上篇】 (背景介绍、初步体验、框架移植)
  2. 【STM32开发笔记】移植AI框架TensorFlow到STM32单片机【下篇】 (平台适配、编译集成、基准测试)
  3. 【STM32开发笔记】移植AI框架TensorFlow到STM32单片机【DSP指令加速篇】 (CMSIS-NN简介、TFLM+CMSIS-NN集成、TFLM+CMSIS-NN测试)

一、前文回顾

此系列前面已经发布了两篇:

  1. 【STM32开发笔记】移植AI框架TensorFlow到STM32单片机【上篇】

  2. 【STM32开发笔记】移植AI框架TensorFlow到STM32单片机【下篇】

【上篇】介绍了TensorFlow、TensorFlow Lite、TensorFlow Lite for Microcontrollers(TFLM)是什么,如何下载TFLM源码,如何在个人电脑(PC)上体验运行TFLM基准测试。同时,分析了TFLM的部分Makefile源码分析。最后,介绍了如何移植TFLM的主体代码。

【下篇】介绍了如何准备STM32 CubeMX项目(以便于后续的TFLM可以顺利移植),如何将TFLM源码集成到STM32 CubeMX生成的项目中去,以及如何在STM32项目中运行TFLM基准测试。同时,介绍了过程中遇到的问题,以及解决方法。最后,给出了整个项目的完整可运行源代码。

二、CMSIS-NN简介

2.1 为什么介绍CMSIS-NN?

因为TFLM源码中有针对CMSIS-NN的算子适配层,通过该适配层可以实现将TensorFlow Lite模型的推理计算转化为对CMSIS-NN库的调用。

同时,CMSIS-NN底层支持DSP指令和MVE指令,在Cortex-M4、Cortex-M7、Cortex-M33上可以实现DSP指令加速计算,在Cortex-M55、Cortex-M85上可以实现MVE加速计算

简言之,TFLM默认的算子实现为纯CPU计算,而CMSIS-NN可以作为TFLM的后端,实现部分处理器上的DSP和MVE加速计算。

2.2 CMSIS-NN是什么?

CMSIS-NN是什么?官方的解释是:

CMSIS NN 软件库是一组高效的神经网络核(函数),旨在最大限度地提高 Arm Cortex-M 处理器上神经网络的性能并最大限度地减少内存占用。

CMSIS-NN是一个计算库,它向上提供了神经网络(NN)计算接口,实现了神经网络计算的硬件加速。它内部实现了纯CPU计算、DSP计算、MVE计算,屏蔽了底层硬件的具体细节,降低了编程难度。

2.3 CMSIS-NN核心特性

总结一下官方的介绍,可以知道CMSIS-NN库的核心特性:

  • 专为Cortex-M处理器开发;

  • 神经网络计算函数;

  • 最大化性能;

  • 最小化内存占用;

  • CMSIS-NN的硬件和软件支持

2.4 CMSIS-NN算子支持

在CMSIS-NN源码仓首页,可以看到CMSIS-NN库提供了三种算子实现,分别为:

  • 纯C,CMSIS-NN提供了所有算子的纯C实现,用于像Cortex-M0和Cortex-M3这样的处理器;
  • DSP扩展,在支持DSP扩展的处理器上,可以使用DSP指令加速计算,例如Cortex-M4或Cortex-M7;
  • MVE扩展,在支持ARM Helium技术的处理器上,可以使用MVE指令加速计算,例如 Cortex-M55 或 Cortex-M85;

三、TFLM+CMSIS-NN集成

接下来,我将介绍如何将TFLM和CMSIS-NN集成到STM32项目中。

3.1 包含TFLM的STM32项目

前面的文章中,我们已经知道了如何将TFLM集成到STM32项目中,本文将以上一篇文章的代码为基础,继续进行CMSIS-NN的集成和测试。

基础项目代码仓链接:

https://gitcode.com/xusiwei1236/STM32H7S78-DK-TFLM

这个代码仓就是——已经包含了TFLM的STM32项目。

3.2 理解TFLM中CMSIS-NN相关构建规则

TFLM的构建规则Makefile文件中,和CMSIS-NN相关的主要代码片段为:

tflm-makefile-638

这段代码中,比较重要的有两处,分别为:

  • 649行,CMSIS-NN对应的OPTIMIZED_KERNEL_DIR变量值为cmsis_nn,此时会包含cmsis_nn.inc构建规则文件;
  • 651到653行,调用specialize_files.py脚本,用于将算子实现源文件列表MICROLITE_CC_KERNEL_SRCS中的部分文件替换为CMSIS-NN适配源文件列表;

cmsis_nn.inc文件内容如下:

cmsis_nn_inc

这段代码中,可以看到TFLM支持两种方式和CMSIS-NN集成:

  • CMSIS-NN作为独立的三方库,链接到一起;
  • CMSIS-NN作为TFLM的一部分,编译到一起;

specialize_files.py文件源码如下:

specialize_files_py

该文件实现了:

  • 遍历base_files列表中的条目,检查在specialized_directory目录下是否存在和它的基础文件名(basename)相同的文件;
  • 如果存在,则使用specialized_directory目录下的替换掉base_files中的这一条;
  • 否则,保持原来位于base_files中的这一条不变!

3.3 理解TFLM中CMSIS-NN相关算子实现

对于CMSIS-NN,实际运行时的specialized_directory指定的参数值是tensorflow/lite/micro/kernels/cmsis_nn子目录。

该目录下包含的文件如下:

image-20241016001239443

实际执行specialize_files.py脚本时,实际的替换文件的对应关系如下:

默认算子文件CMSIS-NN算子文件
tensorflow/lite/micro/kernels/add.cctensorflow/lite/micro/kernels/cmsis_nn/add.cc
tensorflow/lite/micro/kernels/batch_matmul.cctensorflow/lite/micro/kernels/cmsis_nn/batch_matmul.cc
tensorflow/lite/micro/kernels/conv.cctensorflow/lite/micro/kernels/cmsis_nn/conv.cc
tensorflow/lite/micro/kernels/depthwise_conv.cctensorflow/lite/micro/kernels/cmsis_nn/depthwise_conv.cc
tensorflow/lite/micro/kernels/fully_connected.cctensorflow/lite/micro/kernels/cmsis_nn/fully_connected.cc
tensorflow/lite/micro/kernels/mul.cctensorflow/lite/micro/kernels/cmsis_nn/mul.cc
tensorflow/lite/micro/kernels/pooling.cctensorflow/lite/micro/kernels/cmsis_nn/pooling.cc
tensorflow/lite/micro/kernels/softmax.cctensorflow/lite/micro/kernels/cmsis_nn/softmax.cc
tensorflow/lite/micro/kernels/svdf.cctensorflow/lite/micro/kernels/cmsis_nn/svdf.cc
tensorflow/lite/micro/kernels/transpose_conv.cctensorflow/lite/micro/kernels/cmsis_nn/transpose_conv.cc
tensorflow/lite/micro/kernels/unidirectional_sequence_lstm.cctensorflow/lite/micro/kernels/cmsis_nn/unidirectional_sequence_lstm.cc

这里以第一行add.cc为例,默认的算子实现主体代码为:

tf-add-cc

CMSIS-NN版本的add.cc代码主体代码为:

tf-add-cmsis-nn

都提供了Register_ADD()函数,用于注册ADD算子。

3.4 集成CMSIS-NN方式1——作为TFLM的一部分

理解了前面的Makefile代码,就可以编写CMake构建规则,从而实现在STM32项目中集成TFLM和CMSIS-NN。

前文提到,STM32项目集成CMSIS-NN有两种方式,分别为:

  • CMSIS-NN作为TFLM的一部分,编译到TFLM的静态库(libtflite-micro.a)文件中;
  • CMSIS-NN作为独立的三方库,链接到STM32的可执行程序(.elf)文件中;

首先,介绍第一种方式,也就是CMSIS-NN作为TFLM的一部分;这种方式Appli子项目不直接依赖CMSIS-NN库,无需修改,更易于理解。

基于对Makefile源码的理解,修改tflite-micro目录的CMakeLists.txt文件内容:

tflm-cmakelists-diff

这段修改中包含了cmsis-nn.cmakecmsis-nn.cmake文件的内容为:

cmsis-nn.cmake

整个修改实现了:

  • 调用specialize_files.py脚本,将MICROLITE_KERNEL_CC_SRCS中的部分算子文件路径替换为cmsis_nn目录内的,实现了CMSIS-NN适配层的编译;
  • cmsis-nn.cmake中匹配到的CMSIS-NN源文件,添加到TFLM库的源文件列表中,实现了CMSIS-NN代码的编译,并作为TFLM库的一部分;

这样修改之后,重新编译生成的libtflite-micro.a中就包含了CMSIS-NN的代码,以及基于CMSIS-NN的TensorFlow算子实现。

3.5 集成CMSIS-NN方式2——作为独立的三方库

另外一种集成CMSIS-NN的方式是,CMSIS-NN作为独立的三方库,最终连接到整个项目的可执行文件(.elf)中。

要实现这种继承方式,需要在刚修改的TFLM的CMakeLists.txt的基础上进行修改:

tflm-cmakelists-diff-2

一共修改两处:

  • add_library代码片段,删除CMSIS-NN相关的代码文件;
  • 文件末尾添加add_subdirectory(tensorflow/lite/micro/tools/make/downloads/cmsis_nn),让CMSIS-NN的CMakeLists.txt被包含到整个项目中;

除此之外,还需要修改Appli目录的CMakeLists.txt文件,具体修改内容如下图:

Appli-CMakeLists.diff

一共修改了三处:

  • 新增了TF_CMSIS_NN_DIR变量定义,用于记录cmsis_nn源码所在子目录;
  • target_link_directories下,增加一行,指定CMSIS-NN库文件生成的目录;
  • target_link_libraries下,增加一行,指定链接cmsis-nn库;

以上这种修改方式,也可以实现将TFLM和CMSIS-NN集成到STM32项目中。

四、TFLM+CMSIS-NN测试

4.1 编译源代码

第一种方式集成CMSIS-NN,由于上层代码不依赖CMSIS-NN库,即不新增库依赖;因此,其编译方式和此前的文章方式一样,这里不在介绍。

这里仅介绍第二种方式集成CMSIS-NN的编译方法,分为如下几步:

  1. 清理输出目录,如下图操作:

    image-20241019205845206

  2. 编译tflite-micro库,如下图操作:

    image-20241019210234667

  3. 编译xxx_benchmark库,如下图操作:

    image-20241019210123597

  4. 编译cmsis-nn库,如下图操作:

    image-20241019210824201

  5. 编译Appli目标,如下图操作:

    image-20241019210320714

  6. 编译Boot代码,如下图所示:

    image-20241019210403135

4.2 下载Boot代码

由于Appli代码需要使用Boot代码进行跳转,因此,下载Appli代码之前,需要先将Boot代码下载到开发板上。

下载之前,先将STM32H7S78-DK开发板和PC通过USB线连接好,板子由三个USB口,注意连接到标有STLK的。

下载Boot代码,按照如下图所示操作:

image-20241019213805347

执行过程中终端子窗口会输出进度等信息:

image-20241019213920660

4.3 下载Appli代码

下载Appli代码,按照如下图操作:

image-20241019211731626

执行过程中终端子窗口会输出进度等信息:

image-20241019213610487

4.4 运行TFLM基准测试

打开MobaXterm,添加会话,选择STLink的虚拟串口设备,参数如下:

image-20241019020056378

连接设备之后,按下开发板上的NRST按钮,重启设备,可以看到串口输出如下:

20241014234609

可以看到,开发板上,运行有人图像的人体检测耗时为286毫秒,没有人的耗时为286毫秒;连续运行10次的耗时分别为2863毫秒和2863毫秒,速度有点慢。

和上一篇文章的数据对比如下:

测试项目TFLMTFLM+CMSIS-NN
WithPersonDataIterations(1)993286
NoPersonDataIterations(1)994286
NoPersonDataIterations(10)99382863
NoPersonDataIterations(10)99402863

五、问题解决

第三章、第四章实际过程中遇到了一些问题,为了保持前文逻辑连贯,没有在前面记录,本章将记录具体问题及解决方法。

5.1 specialize_files.py 输入不支持CMake列表参数问题

【问题现象】specialize_files.py脚本输出和输入参数base_files的值完全一样。

【问题原因】specialize_files.py脚本使用Python的string.split对参数base_files的值进行分隔,要求值是空白字符(空格、TAB、换行等)分隔的。而CMake的列表字符串是分号分隔的。

【解决方法】将MICROLITE_CC_KERNEL_SRCS中的分隔符替换为空格,再将其传给specialize_files.py脚本,具体代码为:

specialize_files_py_input

5.2 specialize_files.py 输出的路径分隔符不一致问题

【问题现象】specialize_files.py 输出的路径分隔符不一致,有正斜杠也有反斜杠,导致后续报错——文件找不到。

【问题原因】CMake代码使用的路径分隔符是正斜杠,specialize_files.py代码里面使用的是os.path.sep,在Windows上是反斜杠。

【解决方法】将反斜杠全部替换为正斜杠。

specialize_files_py_ouput2

5.3 specialize_files.py 输出和CMake列表格式不一致问题

【问题现象】specialize_files.py 输出的文件列表是空格分隔的,和CMake列表格式不一致。

【问题原因】specialize_files.py 使用空格拼接文件列表为一个字符串之后输出,而CMake列表需要用使用分号分隔。

【解决方法】将字符串中的空格替换为分号。

specialize_files_py_ouput3

5.4 specialize_files.py 输出的最后一个文件无法找到

【问题现象】specialize_files.py 输出的文件列表的最后一个文件,后续CMake代码提示该文件找不到。

【问题原因】乍看起来文件路径是对的,能够找到;实际将该文件路径字符串加上双引号输出之后,发现末尾多了一个换行符。

【解决方法】去除末尾的空白字符。

specialize_files_py_ouput1

六、项目源码

如需本文修改后项目源码的,请在评论区留言。我将会在留言超过10条,或本文阅读量超过1200之后,将本文修改的最终源码全部开源。

当然,动手能力强的读者,也可以根据文章描述的步骤,一步步修改得到最终版本的源码。

七、参考链接

  1. TensorFlow Lite for Microcontrollers介绍: TensorFlow Lite for Microcontrollers (google.cn)
  2. TensorFlow Lite for Microcontrollers入门: 微控制器入门 | TensorFlow (google.cn)
  3. tflite-micro 源码仓: https://github.com/tensorflow/tflite-micro
  4. CMake最新文档: CMake Reference Documentation — CMake 3.30.3 Documentation
  5. CMSIS-NN在线文档: CMSIS-NN: CMSIS NN Software Library (arm-software.github.io)
  6. CMSIS-NN 源码仓: https://github.com/ARM-software/CMSIS-NN

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在Windows平台下基于Whisper来训练自己的数据

0. 简介 最近快到1024程序员节了,再给大家上点干活。Whisper是openai开源的一个语音转文字模型。也是现在识别效果最好的离线数据模型,但是我们发现我们在完成一些中英文或者专业术语对话的时候。这时候表现的效果就比较差了。而这一步就得用微调的方式…

EM算法(期望最大算法、Expectation Maximization Algorithm)

EM算法(期望最大算法、Expectation Maximization Algorithm) 引言 EM算法,全称为期望最大(Expectation Maximization)算法,是一种从不完全数据或有数据丢失的数据集(存在隐含变量)中求解概率模…

Oracle单实例静默安装

oracle 11g单实例静默安装 在CentOS上静默安装Oracle数据库 引言 在企业环境中,自动化和标准化是提高效率的关键。静默安装(也称为无人值守安装)是一种无需人工干预的安装方法,适用于大规模部署或需要重复安装的场景。本文将介…

【redis】初识非关系型数据库——redis

W...Y的主页 😊 代码仓库分享💕 初识 Redis Redis是⼀种基于键值对(key-value)的NoSQL数据库,与很多键值对数据库不同的是,Redis 中的值可以是由string(字符串)、hash&#xff0…

【Python爬虫实战】多进程结合 BeautifulSoup 与 Scrapy 构建爬虫项目

#1024程序员节|征文# 🌈个人主页:易辰君-CSDN博客 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html ​ 前言 在大数据时代,爬虫技术是获取和处理网络数据的利器。面对需要处理大…

ChatGPT实现旅游推荐微信小程序

随着旅游行业的快速发展,个性化推荐已成为提升用户体验的重要手段。通过AI技术,提供一个智能旅游推荐小程序,使用户能够轻松获取定制化的旅行建议。 项目概述 项目目标 开发一个AI旅游推荐小程序,基于用户输入的旅行偏好&#…

Visual Studio安装图文详解教程

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl 教程说明 本教程旨在详细介绍 Visual Studio 社区版的安装过程及其注意事项。 Visual Studio简介 Visual Studio 社区版功能完备且可扩展的免费 IDE,可用于创…

【WPF】中Dispatcher的DispatcherPriority参数使用

在 WPF 中,DispatcherPriority 参数用于指定通过 Dispatcher 调度的操作的执行优先级。加入 DispatcherPriority 参数的情况通常取决于你希望操作何时以及如何被执行。 1.Dispatcher的DispatcherPriority参数使用 以下是几种情况和示例说明: 1.1 需要…

【STM32 Blue Pill编程实例】-控制步进电机(ULN2003+28BYJ-48)

控制步进电机(ULN2003+28BYJ-48) 文章目录 控制步进电机(ULN2003+28BYJ-48)1、步进电机介绍2、ULN2003步进电机驱动模块3、硬件准备及接线4、模块配置3.1 定时器配置3.2 ULN2003输入引脚配置4、代码实现在本文中,我们将介使用 STM32Cube IDE 使用 ULN2003 电机驱动器来控制28B…

自由学习记录(14)

unity操作问题 位置:子物体的位置是相对于父物体的。如果你移动父物体,子物体会保持相对于父物体的相对位置,跟着一起移动。 旋转:子物体的旋转也是相对于父物体的。旋转父物体会导致子物体围绕父物体的原点旋转。 缩放&#xf…

【HarmonyOS NEXT】鸿蒙开发环境准备

0. 引言 看了发布会以后,热血澎湃啊,是时候学学把自己做的一些小工具搞成鸿蒙版了!!! 1. 开发工具下载 下载地址:https://pan.quark.cn/s/08ddebdb7a20 工具版本会不定时更新,下载最新版即可…

【网络原理】——HTTP协议、fiddler抓包

阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 一:认识HTTP 1:超文本传输 2:发展历史 3:HTML 4&am…

Axure树形菜单展开与折叠

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 课程主题:Axure树形菜单展开与折叠 主要内容:树形菜单制作——层级关系——隐藏与显示——值的变化——多层交互 应用场景:关系树、菜…

R语言机器学习算法实战系列(十)自适应提升分类算法 (Adaptive Boosting)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍原理步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割调节参数构建模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve特征的重要性保存模型总…

断点续传技术是什么?大型文件传输的新模式!

随着科技的不断进步,文件传输已成为我们日常生活和工作中不可或缺的一部分。然而,传输大型文件时常常会遇到网络不稳定、传输中断等问题,导致传输失败或者重新传输。为解决这一问题,断点续传技术应运而生。 一、断点续传技术是什么…

3GPP协议解读_NTN系列(一)_38.811_非地面网络(NTN)的背景、应用场景和信道建模

非地面网络 1. Scope4. 非地面网络背景介绍4.1 5G中的非地面网络4.2 非地面网络在5G中的用例4.3 卫星和空中接入网的架构4.4 卫星和空中接入网终端的特点4.5 空气/星载飞行器特性4.6 NTN的覆盖模式4.7 NTN网络架构选项4.8 频谱 5. 非地面网络应用场景5.1 应用场景概览5.2 属性介…

STM32通信协议-I2C

目录 一,IC2的协议规则 I2C总线是PHILIPS公司开发的两线式串行总线,I2C总线主要解决了单片机一对多通信的问题 两根通信线:SCL,SDA,同步,半双工通信,支持数据应答机制,支持总线挂载多设备。 …

2024ideaUI切换和svn与git的切换,svn的安装和配置,idea集成svn ,2024-10-18日

2024-10-18日 2024的UI实在很不舒服,隐藏了很多按键; 第一步: 视图 -》 外观 -》 工具栏选出来; 结果出来: 运行的按键和设置的按钮 第二步 点击设置的按钮,选择最后一个,重启就行 结果 舒服&…

网站漏扫:守护网络安全的关键防线

网站漏洞扫描,简称漏扫,是一种针对网站进行漏洞检测的安全服务。网站漏洞扫描在网络安全中占据着至关重要的地位。 网站漏扫在及时发现和修复漏洞方面发挥着关键作用 通过对网站和系统的全面扫描,能够快速识别出各种潜在的漏洞,…

网络安全领域推荐证书介绍及备考指南

在网络安全领域,拥有专业认证不仅可以证明个人的专业能力,还能帮助在实际工作中应用先进的技术和知识。以下是几种热门的网络安全证书介绍及备考指南。 1. OSCP (Offensive Security Certified Professional) 证书简介 OSCP是针对渗透测试领域的入门级…