Toybrick

标题: RK1808入门教程(1)1808多计算棒并行运算思路分析 [打印本页]

作者: jefferyzhang    时间: 2019-8-23 10:34
标题: RK1808入门教程(1)1808多计算棒并行运算思路分析
本帖最后由 jefferyzhang 于 2019-10-12 09:49 编辑

[attach]503[/attach]

简介:

1808计算棒作为一个扩充运算单元,是完全可以组成计算棒阵列运算的。这里我们会提出几种思路讨论,并提供一个主动模式的多计算棒运行Sample给大家。
一般来说,使用多计算棒组成阵列的目的是为了:

1. 后端集群运算,避免前端重新改造。
2. 整合计算资源,共享计算资源,提高资源利用率。
3. 解决单个计算棒计算瓶颈,提高帧率。
4. 为上位机提供更多算力。


思路分析:

针对不同的需求,一般来说有3种设计思路:

1.  每个计算棒拥有同样的一个或多个完整模型,通过负载均衡分配每个计算棒推理任务。
2.  每个计算棒只运行模型的一部分,多个计算棒流水线作业,共同计算完成一个模型。
3.  每个计算棒拥有不同的模型,一个上位机通过连接多个计算棒同时进行多种模型的计算。(DEMO主要提供这种)

对于第一种情况:多个计算棒都在运行同一种模型,针对每个计算棒进行负载均衡,那么就可以通过重复瓶颈的方式提高帧率。运行速度取决于重复瓶颈的数量。
对于第二种情况:需要将一个模型拆分成多个子模型,分布在不同的计算棒上做成流水线串行运算,那么就可以通过拆分瓶颈的方式提高帧率。运行帧率取决于最慢的那个子模型。
对于第三种情况:有些案例是需要多个模型协作的,那通过部署多个计算棒,每个计算棒运行单一模型,可以直接扩充上位机运算能力。


三种情况其实对于上位机和计算棒的物理连接并没有太大区别,仅仅是之间的软件设计交互不同而已。
下面我们针对最简单的第三种情况来进行实例操作。


物理连接方式:

[attach]493[/attach]

1. 计算棒切为主动模式运行。主动模式计算棒会虚拟为一个USB网卡和上位机通讯
2. 多个计算棒通过USB和上位机相连
3. 多个IPCamera通过以太网和上位机网卡相连


网络拓扑:

[attach]494[/attach]

1. 网络结构上,计算棒通过上位机桥接,得到和上位机、IPCamera同一个网段IP。
2. 所有设备数据都在同一网段收发,这样开发上就方便了许多。


1808计算棒业务逻辑:

1. 直接通过网络获取需要的数据流(本Demo里是通过rtsp获取ipcamera数据)
2. 进行网络推理,处理输出结果。
3. 将最终推理结果发送给上位机


上位机业务逻辑:

1. 控制计算棒开关和工作模式,分配计算棒工作任务
2. 接受各个计算棒发来的结果数据
3. 对结果数据进行应用(本Demo不做其他应用)


FAQ:

Q:计算棒能否支持及联?
A:支持,需要自己开发逻辑代码,没有通用业务逻辑。计算棒仅仅是作为一个运算单元使用而已,不写代码他是不会知道你想如何及联或并行运算的。

Q:如何拆分模型?
A:转换RKNN时候根据设定不同的input和output节点来实现模型的拆分(建议不要拆散“卷积-激活-池化”这样一组操作)。

Q:被动模式是否可以多计算棒运行?
A:可以,在支持被动模式的上位机上可以识别不同计算棒ID,通过ID指定运行的计算棒(当前版本C/Python均已支持

Q:主动模式是否可以多计算棒运行?
A:可以,主动模式和上位机会识别成USB网卡,插入多个计算棒相当于插入了多个网卡,根据你的路由器或者DHCP服务器,每个计算棒都会有一个独立IP可以访问

Q:上位机Linux如何桥接计算棒?
A:二楼Sample里我会放出脚本。


------------- Sample 请继续看2楼 -------------->
作者: jefferyzhang    时间: 2019-8-23 10:34
本帖最后由 jefferyzhang 于 2019-8-28 10:44 编辑

多计算棒SAMPLE


附件1  Linux上位机桥接脚本:


[attach]496[/attach]

(执行之前请先ifconfig确认下节点名字。)

a. 桥接eth0 和 usb0 usb1
  1. chmod +x bridge-setup.sh
  2. ./bridge-setup.sh eth0 usb0 usb1
复制代码

b. 断开桥接 br0:
  1. chmod +x bridge-clean.sh
  2. ./bridge-clean.sh br0
复制代码



附件2 1808计算棒运行脚本(主动模式):

[attach]498[/attach]

a. Python功能库安装
  1. dnf install -y python3-numpy libdrm
  2. pip3 install toybrick-0.1.9-py3-none-any.whl
复制代码

b. Rockx功能库安装(1808)
  1. dnf install rockx
复制代码

c. 桥接1808后,需要将1808改为DHCP模式从外部路由器获取IP地址。
(具体参看wiki:http://t.rock-chips.com/wiki.php?mod=view&id=63

d. 模型脚本执行方式(每个计算棒运行一个)
  1. ./tb1808_body.py <id>
  2. ./tb1808_obj.py <id>
复制代码
其中<id>为sample的1808索引,其中一个写1,另外一个就要写2


附件3 上位机运行脚本

[attach]499[/attach]

a. 运行方式:
  1. ./root/host_server.py
复制代码


b. 说明:
由于上位机不一定是Toybrick设备,所以代码里注释掉了仅在toybrick上可绘制的效果图部分,大家其实可以改成所有设备通用的OpenCV显示方式。
但是真正项目应该不会去绘制这些debug信息,可接收到上位机发来的信息即可。


计算棒配置说明:

首先要进入计算棒将计算棒改为主动模式和DHCP模式,具体教程参见wiki:http://t.rock-chips.com/wiki.php?mod=view&id=63
配置完DHCP后你可能无法即使得知计算棒的IP地址,这时候可以使用nmap命令等方式来扫描网段端口,得知计算棒的内网IP:
  1. nmap 192.168.1.1-254 -p 22 --open    # 其中192.168是你DHCP的网段
复制代码
1808改为DHCP模式后他默认的192.168.180.8的IP还是存在的,也可以通过这个IP单独访问计算棒


上位机和1808计算棒交互说明

1. 上位机启动脚本里会启动一个广播线程,不停的向网络广播自己位置和摄像头地址以及每个摄像头任务需求2. 计算棒启动时候接收广播,就可以知道对应任务的摄像头地址(数据流获取地址)和上位机地址(结果发送地址)
3. 计算棒做成开机自启动方式,这样计算棒就无需改动,修改上位机广播内容就可以通知计算棒获取对应任务的数据地址。


配置计算棒开机启动

  1. vi /usr/local/bin/tb.local.after
复制代码
将运行脚本加入尾部,例如:
  1. python3 ./tb1808_body.py 1 > /dev/null &
复制代码



上位机EAIDK310双计算棒演示程序搭建包(RK展会双计算棒演示程序):
链接: https://pan.baidu.com/s/1inq6XfcgwuAXhrihXjKS1Q 提取码: r435

注意:
1. 如果你的上位机不是EAIDK310,是无法显示的,但是可以收到双计算棒处理后的数据
[attach]515[/attach][attach]514[/attach]


作者: sanshin    时间: 2019-8-26 11:11
jefferyzhang 发表于 2019-8-23 10:34
多计算棒SAMPLE

楼主,请问一个具体问题,请给出一点建议?
》1.  每个计算棒拥有同样的一个或多个完整模型,通过负载均衡分配每个计算棒推理任务。
》2.  每个计算棒只运行模型的一部分,多个计算棒流水线作业,共同计算完成一个模型。
》3.  每个计算棒拥有不同的模型,一个上位机通过连接多个计算棒同时进行多种模型的计算。(DEMO主要提供这种)
2和1,3还有一个区别。就是模型的大小不同。
1和3都是针对那些可以完整的下载到1808里面的模型。
2的话可以下载更大的模型。比如跑在jetson上的模型分割后放在几个1808上。
除了分割模型,还有几个问题
  a,目前的API是否够用?(目前API有没有验证过可以实现?)
在目前的API下,客户是否可以自由的操作INT8 MAC?
客户需要把数据送到每一个1808,然后再把中间结果读出来,再写到下一级1808里面,这个读写过程有2个问题
  b,根INT8 MAC运算相比,这个读写(USB/PCIe)如果消耗时间太长,那么这个方法本身就不现实。(不若直接在一个jetson上面装一个大模型)
  理想状态应该是几个1808级连以后可以达到一个jetson的功能以及算力,如果不管多少个1808级连在一起,只会越来越慢(USB/PCI3太慢),这个方法本身就不可取。
我不知道INT8MAC运算需要多少clock,估计应该比USB/PCIe更快,
c,rockchip有没有计划提供一个把模型拆分成多个子模型,分布在不同的计算棒上做成流水线串行运算的sample?

作者: jefferyzhang    时间: 2019-8-26 11:19
sanshin 发表于 2019-8-26 11:11
楼主,请问一个具体问题,请给出一点建议?
》1.  每个计算棒拥有同样的一个或多个完整模型,通过负载均 ...

a. 目前API完全够用,我们经常有将网络拆分使用的情况(例如不支持的op会拆到上位机中cpu或者gpu运算),但是没有拆给其他1808运算的sample。用户无法直接操作NPU的运算单元,但是可以通过转换为RKNN的计算图形式交给NPU运算。

b. 拆分模型的目的是为了在当前方案下达到足够的帧率,流水线作业可以保证帧率,但是延迟是会变高的(如你说的读写传输是会加大延迟的)。每个芯片方案都有各自的优缺点,我们社区也只能跟当前方案对比,无法跟jetson对比。

c. 暂时没有这样的sample。
作者: sanshin    时间: 2019-8-26 12:35
jefferyzhang 发表于 2019-8-26 11:19
a. 目前API完全够用,我们经常有将网络拆分使用的情况(例如不支持的op会拆到上位机中cpu或者gpu运算), ...

[url]谢谢,可以问另外一个具体问题吗?
我用一台电脑接3个1808stick(一个直接接电脑,另外2个通过USB3.0 hub接同一台电脑)做测试的时候发现一个问题。请帮忙确认一下,
log data:
E Catch exception when getting outputs.
T Traceback (most recent call last):
T   File "rknn\api\rknn_base.py", line 817, in rknn.api.rknn_base.RKNNBase.inference
T   File "rknn\api\rknn_base.py", line 701, in rknn.api.rknn_base.RKNNBase.get_outputs
T   File "rknn\api\rknn_runtime.py", line 390, in rknn.api.rknn_runtime.RKNNRuntime.get_output
T Exception: RKNN get output failed. Error code: RKNN_ERR_DEVICE_UNAVAILABLE
Traceback (most recent call last):
  File "rknn_camera_tiny_custom.py", line 234, in <module>
    out_boxes, out_boxes2 = rknn.inference(inputs=[image])
TypeError: 'NoneType' object is not iterable
实际使用的命令(由于没有这么多USB相机接口,就用了本地的录像文件)
python3 rknn_camera_tiny_custom.py TS018080190600024 ./movie1.mp4 movie1
python3 rknn_camera_tiny_custom.py TS018080190600158 ./movie2.mp4 movie2
python3 rknn_camera_tiny_custom.py TS018080190600137 ./movie3.mp4 movie3

linux/windows都测试了,结果一样
代码也上传了,请确认一下。
rknn_camera_tiny_custom.py

作者: jefferyzhang    时间: 2019-8-26 12:36
本帖最后由 jefferyzhang 于 2019-8-26 12:50 编辑
sanshin 发表于 2019-8-26 12:35
谢谢,可以问另外一个具体问题吗?
我用一台电脑接3个1808stick(一个直接接电脑,另外2个通过USB3.0 hub ...

请看一楼FAQ,目前python的被动模式API是不支持多计算棒的。
请使用c api;或者计算棒主动模式
作者: sanshin    时间: 2019-8-26 13:54
jefferyzhang 发表于 2019-8-26 12:36
请看一楼FAQ,目前python的被动模式API是不支持多计算棒的。
请使用c api;或者计算棒主动模式 ...

谢谢,
请问是否可以提供一个动作测试用的3个1808 stick分别跑不同模型的c api的sample吗?

作者: jefferyzhang    时间: 2019-8-26 14:10
sanshin 发表于 2019-8-26 13:54
谢谢,
请问是否可以提供一个动作测试用的3个1808 stick分别跑不同模型的c api的sample吗?
...

自己写吧,我们API文档都有提供那么详细了。。。。
作者: sanshin    时间: 2019-8-26 15:06
jefferyzhang 发表于 2019-8-26 14:10
自己写吧,我们API文档都有提供那么详细了。。。。

请问你们没有测试代码吗?测试代码也可以?
我们自己写也可以,但是没有找到说明文档,都是python的。
怎么用c api来指定不同1808的ID? 用什么API?
作者: jefferyzhang    时间: 2019-8-26 15:32
sanshin 发表于 2019-8-26 15:06
请问你们没有测试代码吗?测试代码也可以?
我们自己写也可以,但是没有找到说明文档,都是python的。
怎 ...

请参看rknn-api 文档《RK3399Pro_Linux&Android_RKNN_API_V0.9.8_20190626》
第3.1.1节:  rknn_init & rknn_init2

rknn_init_extend* extend: 扩展信息的指针,如用于设置或获取当前 init 的信息, 如设置设备的ID号device_id(详见rknn_api.h的rknn_init_extend定义)。如不用, 可赋 NULL。
作者: sanshin    时间: 2019-8-26 16:35
jefferyzhang 发表于 2019-8-26 15:32
请参看rknn-api 文档《RK3399Pro_Linux&Android_RKNN_API_V0.9.8_20190626》
第3.1.1节:  rknn_init & r ...

Thanks a lot. We will have a try.
作者: wuzhiyong    时间: 2019-12-18 20:14
我们准备采购RK1808芯片来设计IOT硬件模组,请问如果LPDDR3颗粒和EMMC颗粒换成跟参考设计中不同型号的器件,还能正常运行起来么?
作者: wuzhiyong    时间: 2019-12-18 20:18
CPU运行万BootRom后,接着运行lpddr初始化程序,这段程序能够提供源代码么?便于我们调试和修改参数,避免因更换lpddr3颗粒型号导致系统无法运行。
作者: xmhy66    时间: 2020-4-7 12:38
jefferyzhang 发表于 2019-8-26 12:36
请看一楼FAQ,目前python的被动模式API是不支持多计算棒的。
请使用c api;或者计算棒主动模式 ...

什么是计算棒主动模式?
作者: jefferyzhang    时间: 2020-4-7 14:17
xmhy66 发表于 2020-4-7 12:38
什么是计算棒主动模式?

主动模式: 把计算棒当开发版,直接在计算棒上运行程序,和上位机通过计算棒之间的虚拟网卡socket编程交互。

被动模式:把计算棒当计算资源,在上位机开发程序,通过调用rknn接口让计算棒进行运算。
作者: xmhy66    时间: 2020-4-7 16:38
有被动计算的demo吗?计算棒的算力与3399pro比,差别大吗?
作者: frank-edw    时间: 2020-7-28 15:21
1)RK3399 可以通过USB3.0同时接入两个RK1808计算棒吗?,他们的API能否支持俩个计算棒同时计算处理?
2)如果用usb3.0,底层的数据交换协议是否就是usb3.0?
作者: jefferyzhang    时间: 2020-7-29 08:25
frank-edw 发表于 2020-7-28 15:21
1)RK3399 可以通过USB3.0同时接入两个RK1808计算棒吗?,他们的API能否支持俩个计算棒同时计算处理?
2) ...

1. 可以,api通过init_runtime区分运行的计算棒
2. 是的
作者: jefferyzhang    时间: 2020-7-29 08:26
xmhy66 发表于 2020-4-7 16:38
有被动计算的demo吗?计算棒的算力与3399pro比,差别大吗?

同样的NPU,demo论坛和rknntoolkit、rknnapi里都有




欢迎光临 Toybrick (https://t.rock-chips.com/) Powered by Discuz! X3.3