0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何把Tengine Python API移植到Tengine Lite上

电子设计 来源:电子设计 作者:电子设计 2020-12-15 00:30 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

大佬说选择移植Tengine Python API这个任务,一方面是因为他之前做过涉及Python和C++/C交互的开源项目工作,如 MXNet 中DLPack的Python API和他自己的开源项目 MobulaOP,这些工作让他踩了不少的坑;另一方面是因为他认为,了解一个框架需要先把例子跑起来, 就像学习一门新的编程语言要先跑通它的Hello World程序。通过这次任务,可以了解基于Tengine Lite的图像分类实现,对TengineLite有一个初始的、直观的感受。

以下为大佬第一人称自述/~

初探源码

这个任务的工作可以用一句话来概括: 在Tengine跑起Python例子, 再在Tengine Lite跑起同样的例子。

第一步需要找到Tengine Python API的例子。但Tengine没有的Python例子, 也没有Python API的文档。想从单元测试入手,但也没有Python API的单元测试,难怪移植Python API的任务难度比移植C++ API的任务难度高。还有什么方法可以了解Python API的用法呢? 阅读源码。Tengine的Python API放在pytengine文件夹, 里面有八个模块,分别是:base、context、device、 graph、libinfo、node、tengine和tensor,可以重点关注base, graph和tensor。

从base.py源码中可以看出Tengine使用ctypes的形式进行Python和C++/C的交互,把动态链接库libtengine.so读取后保存到变量/_LIB中,通过/_LIB.可以调用Tengine的C API. graph.py实现计算图部分的API,tensor.py实现了作为输入和输出的张量API。

编译和导入模块

找到Python API代码的位置后,编译Tengine,并尝试在Python中导入tengine模块。从libinfo.py中可以了解到,Tengine Python API会在Python API目录和环境变量LD/_LIBRARY/_PATH所指向的目录中,查找动态链接库libtengine.so.这时遇到了第一个Bug,我用的操作系统没有定义LD/_LIBRARY/_PATH这个环境变量,而API里直接用下标访问的形式取这个环境变量的值,出现了KeyError的错误。改成os.environ.get('LD/_LIBRARY/_PATH', '')即可。设置好动态链接库的路径后,可以成功导入pytengine模块了。

编写Python分类示例

Tengine提供C++/C的分类示例代码,在examples目录下,可以作为编写Python例子时的参考。其中,classification.cpp用了Tengine的C++ API,比C API多了Net类的封装,Net类封装了对于计算图Graph的操作。而classification/_old/_api.cpp用的是Tengine的C API. 由于Tengine Python API调用的是Tengine C API,因此可以拿classification/_old/_api.cpp作为参考。Tengine Python API封装得很简洁,很容易能找到每个Python函数调用的C函数。C++分类示例代码和Python API的代码互相对照,就可以写出Python分类示例的代码。写完后就可以尝试运行了。

运行Python分类示例

运行Python分类示例并不顺利,一开始就在构建计算图上出错了。定位到Python API的源码后, 发现是在以下两行出错。

# pytengine/tengine/graph.py:L24-L25 
params = [ c_str(item) for item in kwarg] 
self.graph = _LIB.create_graph(ctypes.c_void_p(context), c_str(model), *params)

create/_graph有三个参数: 第一个参数context是模型执行的上下文,第二个参数是模型的格式,第三个参数是模型的文件名。这两行代码看起来没什么毛病,和C++例子里的调用方式是一模一样的。但出错的原因就在给变量params赋值的这一行,里面的item是一个临时变量,当这条语句结束时,item离开了作用域就被释放了。而c/_str(item)是指向原来item的位置,变成了一个野指针。为了解决这个问题,可以把该行改为params = [ c/_str(kwarg[i]) for i in range(len(kwarg)) ],此时c/_str(kwarg[i])指向的是变量kwargs中存储的值,变量kwargs在调用函数create/_graph时仍在作用域内。

另外遇到的一个复杂的问题和Tensor类有关, pytengine的Tensor类还不完善,无法取出Tensor里的数据.。对照C语言写的例子修改Tensor的buf函数,得到数据内存地址,占用的内存大小,类型,尺寸后,转换为NumPy数组。 需要注意一下Tengine Lite前端的执行步骤:

# 建立计算图并读取模型文件
tm_file graph = tg.Graph(None, 'tengine', tm_file) 
# 取出输入
Tensor input_tensor = graph.getInputTensor(0, 0) 
# 设置输入Tensor的尺寸 
dims = [1, 3, img_h, img_w] 
input_tensor.shape = dims
# 预先运行以分配资源, 必须加上 
graph.preRun() 
# 设置输入数据的内存地址, 这里的data是尺寸为(3, img_h, img_w)的NumPy数组. 注意: 这里不会检查shape 
input_tensor.buf = data
# 以同步方式让网络进行推断(前向传播), 其中1表示使用同步的方式 
graph.run(1) # 1 is blocking 
# 取出输出的Tensor 
output_tensor = graph.getOutputTensor(0, 0) 
# 将Tensor转为NumPy数组 
output = np.array(output_tensor.buf)

把这些问题解决后,就能在Tengine上运行Python示例了。

需要注意的是,Tengine Lite和Tengine在做推断前,都需要调用preRun()函数对资源进行分配,这是必须要调用的。 虽然现在的Python API用起来有点复杂,但相信之后会封装得更好的。

从Tengine到Tengine Lite

在Tengine上成功运行Python示例后,移植就变得方便了。直接把pytengine文件夹下的所有代码, 以及Python分类示例复制粘贴到Tengine Lite中,将动态库名称从libtengine.so改为libtengine-lite.so, 然后运行Python分类示例。不出意料,出错了。 原因是Tengine Lite在设置输入Tensor的数据内存地址时,也会检查数据的大小,而之前的Python API的数据大小的计算是错误的。 修复Bug后, 成功在Tengine Lite上运行图像分类示例。移植完成。不得不夸一下Tengine Lite的C API兼容性做得真好!

在EAIDK-310上运行Tengine Lite的Python图像分类示例

之前参加OPEN AI LAB的活动,得到了一块EAIDK-310开发板, 刚好可以在上面进行测试。
这里使用可爱的虎猫(Tiger Cat)作为测试图片,模型采用MobileNet。 图片和模型都可以在Tengine项目的页面中找到链接 (Tengine快速上手指南)。

下载代码

[openailab@localhost proj]$ git clone https://github.com/OAID/Tengine 
# 进入Tengine的目录 
cd Tengine 
[openailab@localhost Tengine]$ git branch 
* tengine-lite

当前Tengine的默认分支是Tengine Lite。

2. 编译Tengine Lite

mkdir build 
cd build 
cmake .. 
make -j2

注意不要把编译线程数设太大,因为在最后编译MobileNet SSD例子时消耗显存比较多。六分钟多可以编译完。

3. 配置Tengine Lite的Python API编辑/home/openailab/.bashrc,再最后一行后面加入:

export TENGINE_LITE_PATH=/home/openailab/proj/Tengine 
export PYTHONPATH=$PYTHONPATH:$TENGINE_LITE_PATH/pytengine 
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TENGINE_LITE_PATH/build/src/

环境变量TENGINE_LITE_PATH设置为Tengine Lite的根目录路径, 设置好后重新打开终端。 打开Python, 能成功导入tengine。

[openailab@localhost examples]$ python 
Python 3.6.5 (default, Mar 29 2018, 17:45:40) 
[GCC 8.0.1 20180317 (Red Hat 8.0.1-0.19)] on linux 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import tengine

4. 将三个文件cat.jpg/, mobilenet.tmfile/, synset/_words.txt放在examples的目录下, 文件结构如下所示:

[openailab@localhost examples]$ pwd 
/home/openailab/proj/Tengine/examples

[openailab@localhost examples]$ tree 
. 
├── cat.jpg 
├── classification.py 
├── mobilenet.tmfile 
├── synset_words.txt

5. 运行examples文件夹下的图像分类示例classification.py

[openailab@localhost examples]$ python classification.py 
n02123159 tiger cat 8.5975923538208 
n02119022 red fox, Vulpes vulpes 7.954988956451416 
n02119789 kit fox, Vulpes macrotis 7.867891311645508 
n02113023 Pembroke, Pembroke Welsh corgi 7.427407264709473 
n02123045 tabby, tabby cat 6.364651679992676

由此,就能够在Tengine Lite上正确预测出虎猫啦 : )

下一步工作

对于Tengine Lite Python API,我觉得在API设计方面可以进一步改进。比如把数据预处理, 计算图构建等操作隐藏起来,比如:

image = cv2.imread('./cat.jpg') 
model = tg.Model(tm_file) 
pred = model(image)

这样可以减少出错概率, 一些错误比如忘记对数据做预处理,使用的数据内存分布(NCHW还是NHWC)不正确,忘记调用prerun。

本次Tengine Python API移植任务,大佬做的工作是编写一个Python的图像分类示例,在Tengine上跑通代码,再将pytengine移植(复制)到Tengine Lite上, 再在Tengine Lite上跑通代码,其中还修复了pytengine中的一些bug。

更多Tengine相关内容请关注Tengine-边缘AI推理框架专栏。

审核编辑 黄昊宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • python
    +关注

    关注

    57

    文章

    4856

    浏览量

    89548
  • Tengine
    +关注

    关注

    1

    文章

    47

    浏览量

    3209
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    淘宝商品详情API接口技术解析与实战应用

    出发,系统解析淘宝商品详情API接口的调用机制、数据结构及典型应用场景,并附上基于Python的完整调用示例,助力开发者高效集成商品数据服务。 关键词 淘宝开放平台;商品详情API;RESTful接口;数据解析;
    的头像 发表于 11-04 09:50 121次阅读

    Python调用API教程

    两个不同系统之间的信息交互。在这篇文章中,我们将详细介绍Python调用API的方法和技巧。 一、用Requests库发送HTTP请求 使用Python调用API的第一步是发送HTTP
    的头像 发表于 11-03 09:15 318次阅读

    移植蜂鸟e203内核A7lite开发板上相关问题的解决办法

    Include: 第六步:将上述的约束文件变更为自己所需要的约束规则。 最后: 分析综合,将高级抽象层次的电路描述转化为较低层次的描述 下图为综合报告: 完成布局布线: 至此,我们已经完成并解决了蜂鸟e203移植A7l
    发表于 10-27 06:35

    Vue3组合式API最佳实践:从Options APIComposition API

    简介 在Vue.js中,Options API一直是主流的开发方式。不过随着Vue3的推出,Composition API作为一种全新的开发方式引起了广泛关注。本文将从Options API
    的头像 发表于 10-20 13:36 157次阅读

    如何移植rt-thread野火imx6ull开发板

    求助如何将rt-thread移植野火imx6ull(coretex-A7)开发板,官方的bsp中没有imx6ull
    发表于 09-29 06:25

    【上海晶珩睿莓1开发板试用体验】将TensorFlow-Lite物体归类(classify)的输出图片移植LVGL9.3界面中

    既然调通了TensorFlow-Lite物体归类(classify)和LVGL9.3代码,那么这两个东西结合起来也是没问题的,需要注意的是,TensorFlow-Lite是C++代码,而
    发表于 09-21 00:39

    产品添加与API接口设计指南

    将以RESTful API为例,使用JSON数据格式,并提供Python代码示例。 1. API接口概述 API接口允许开发者通过HTTP请求管理产品生命周期: 添加产品
    的头像 发表于 07-24 14:45 433次阅读
    产品添加与<b class='flag-5'>上</b>架<b class='flag-5'>API</b>接口设计指南

    鸿蒙开发API9 API12,有哪些不同

    ​ ##HarmonyOS 应用开发## 虽然API9已经属于过时了,但是现在很多学校里教的还是基于API9的鸿蒙开发,当学生需要在毕业设计中使用API12进行开发时,还是需要先掌握一些两者的区别
    发表于 06-29 22:47

    无法将Tensorflow Lite模型转换为OpenVINO™格式怎么处理?

    将 Tensorflow Lite 模型转换为 OpenVINO™ 格式。 遇到的错误: FrontEnd API failed with OpConversionFailure:No translator found for TFLite_Detection_PostP
    发表于 06-25 08:27

    Python从入门精通背记手册

    电子发烧友网站提供《Python从入门精通背记手册.pdf》资料免费下载
    发表于 03-28 17:43 85次下载

    蜂鸟E203的NICE接口如何移植其他RISCV核

    蜂鸟E203的NICE接口移植其他RISCV核
    发表于 03-07 08:49

    使用Python API在OpenVINO™中创建了用于异步推理的自定义代码,输出张量的打印结果会重复,为什么?

    使用 Python* API 在 OpenVINO™ 中创建了用于异步推理的自定义代码。 遇到输出张量的打印结果会重复的问题,即使输入图像不同。
    发表于 03-06 07:53

    DLP6500能否用Python编程进行开发,是否有API接口?

    本人第一次接触DLP的开发板,想知道DLP6500这款板子能否用Python编程进行开发,是否有API接口?
    发表于 02-28 06:58

    如何将RT-Thread移植NXP MCUXPressoIDE

    RT-Thread默认支持的IDE只有IAR 和 Keil, 那如何将RT-Thread移植NXP MCUXPressoIDE呢?本文内容比较简单但稍有琐碎,希望对有需要的小伙伴有所帮助。
    的头像 发表于 02-13 10:37 2431次阅读
    如何将RT-Thread<b class='flag-5'>移植</b><b class='flag-5'>到</b>NXP MCUXPressoIDE<b class='flag-5'>上</b>

    将基于PC的MP3播放器软件移植ADSP-21262 SHARC处理器

    电子发烧友网站提供《将基于PC的MP3播放器软件移植ADSP-21262 SHARC处理器.pdf》资料免费下载
    发表于 01-03 14:54 0次下载
    将基于PC的MP3播放器软件<b class='flag-5'>移植</b><b class='flag-5'>到</b>ADSP-21262 SHARC处理器<b class='flag-5'>上</b>