前两期中我们已经把所有准备工作一步步铺垫到位:
Zephyr迎来AI加速时代:NPU驱动集成从未如此简单
为Zephyr AI加速做好准备:模型转换
现在,是时候把准备工作真正转化为成果了!
今天,我们将正式在Zephyr中加入NPU软件支持,让模型不仅能“跑起来”,还能“跑得飞快”。是的,本期开始就是实战环节!
本次的适配工作将以tflite_micro/hello_world工程为基础展开。我们首先将其完整复制一份,并命名为hello_world_neutron。后续所有与Neutron NPU相关的移植步骤和配置修改,都将在这个新工程中进行。
Zephyr的移植工作我们基于tfltie_micro/hello_world工程进行,将其复制一份重命名为hello_world_neutron:

一、改造思路
整体改造大致分为三个主要步骤:
开启C /FPU/TFLM支持
添加NPU相关驱动与接口层代码
修改CMakeLists.txt让工程真正“认识” NPU
除此之外,还需要将模型文件替换为NPU可执行的版本,并手动注册Neutron自定义算子,使TFLM能够调用NPU。下面我们一步一步来。
二、工程配置
1.修改prj.conf文件,添加FPU与CXX的支持:
CONFIG_CPP=y CONFIG_STD_CPP17=y CONFIG_FPU=y CONFIG_FPU_SHARING=y CONFIG_TENSORFLOW_LITE_MICRO=y CONFIG_MAIN_STACK_SIZE=2048 CONFIG_REQUIRES_FLOAT_PRINTF=y
三、加入NPU相关代码
NPU 的组件大致可分为两部分:
1. Neutron 与 TFLM 的接口层 2. Neutron 底层 Driver
3.1将NPU相关Driver从SDK中拷贝到工程目录中
主要分为两部分:NPU底层Driver以及NPU与TFLM的接口层代码:
a) TFLM接口层代码:
我们可以在SDK代码中的eiq ensorflow-lite ensorflowlitemicrokernels eutron路径下找到这两个文件,
一定要注意:SDK版本要和转换工具的版本一致,这里我们选择的是2.16.0版本的SDK代码以及针对于2.16.0 SDK版本的Neutron-converter.exe:

将这两个文件拷贝到工程目录中:

3.2NPU底层驱动:
可以在eiq ensorflow-lite hird_party eutron路径找到:

将其同样拷贝到工程目录下,完整的目录结构如下:

四、修改CMakeLists,加入NPU依赖
我们需要让工程能够正确包含头文件、链接NPU相关库,完整示例如下:
| cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(tensorflow_hello_world) # These samples use local static initialization. Since Zephyr doesn't support the # C ABI for thread-safe initialization of local statics and the constructors don't # appear to require thread safety, we turn it off in the C compiler. set(NO_THREADSAFE_STATICS $ ) zephyr_compile_options($<$ :${NO_THREADSAFE_STATICS}>) #头文件依赖 target_include_directories(app PRIVATE neutron/driver/include) target_include_directories(app PRIVATE neutron/common/include) target_include_directories(app PRIVATE neutron/source) #库依赖 add_library(libneutron1 STATIC IMPORTED GLOBAL) set_target_properties(libneutron1 PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/neutron/libNeutronDriver.a) add_library(libneutron2 STATIC IMPORTED GLOBAL) set_target_properties(libneutron2 PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/neutron/libNeutronFirmware.a) add_library(libneutron INTERFACE) target_link_libraries(libneutron INTERFACE libneutron1 libneutron2) target_link_libraries(app PUBLIC libneutron) #添加源文件 file(GLOB app_sources src/*) target_sources(app PRIVATE ${app_sources}) target_sources(app PRIVATE neutron/source/neutron.cpp) |
到这里,工程已经具备NPU支持能力。
五、替换模型文件
将src/目录下的model.cpp替换为你通过xxd转换得到的NPU版本模型。
模型来源应为Neutron-converter转换后的.bin,格式已经适配NPU。

六、注册Neutron自定义算子
注册Neutron算子:
因为TFLM本身不支持Neutron算子,这里需要我们手动添加,添加方式是修改src/main_functions.cpp:
| /* This pulls in the operation implementations we need. * NOLINTNEXTLINE(runtime-global-variables) */ static tflite::MicroMutableOpResolver <1> resolver; resolver.AddCustom(tflite::GetString_NEUTRON_GRAPH(), tflite::Register_NEUTRON_GRAPH()); |
因Zephyr自带的模型算子类型是FullyConnected,这里将他替换为NeutronGraph,同时在文件开头添加头文件引用:

至此,所有软件工作就都完成了,接下来就是使用west工具进行编译:
| west build -b frdm_mcxn947/mcxn947/cpu0 |

七、编译,下载运行
使用west编译工程,下载运行:

当我们看到正常输出、并且没有任何错误时,就说明:
模型成功转换
Neutron NPU驱动加载成功
TFLM已正确调度NPU推理
模型已顺利跑在NPU上进行加速!
八、完整链路走通
至此,小编跨越三期,带大家完整走了一遍流程:
1. 自主训练模型
2. 使用转换工具生成NPU 可执行格式
3. 在ZephyrOS 中添加 Neutron NPU 驱动支持
4. 让模型真正跑在NPU 上加速推理
这条链路虽然步骤较多,但每一步都是构建“嵌入式AI”所必需的关键环节。
也期待未来ZephyrOS能继续完善AI支持,让NPU适配更加自动化,让开发者可以更加专注于算法本身。
关注
1文章
415浏览量
29414关注
91文章
39804浏览量
301479免责声明:本文为转载,非本网原创内容,不代表本网观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
如有疑问请发送邮件至:bangqikeconnect@gmail.com