RK3399Pro RKNN-Toolkit 的使用

前言

目前 RKNN-Toolkit 可以运行在 PC(Linux/Windows/MacOS x64)上,也可以运行在 RK3399Pro
开发板(Debian9 或 Debian10)。
本人推荐PC是linux系统,rk3399pro是debian10,原因之后补充。

模型运行在与 PC 相连的 Rockchip NPU 平台上

该场景下,RKNN-Toolkit 运行在 PC 上,通过 PC 的 USB 连接 NPU 设备。RKNN-Toolkit 将RKNN 模型传到 NPU 设备上运行,再从 NPU 设备上获取推理结果、性能信息等。

运行非 RKNN 模型时工具的使用流程

当模型为非 RKNN 模型(Caffe、TensorFlow、TensorFlow Lite、ONNX、Darknet、PyTorch、
MXNet 等模型)时,RKNN-Toolkit 工具的使用流程及注意事项如下:
在这里插入图片描述
注:
1、 以上步骤请按顺序执行。
2、 蓝色框标注的步骤导出的 RKNN 模型可以通过 load_rknn 接口导入并使用。
3、 红色框标注的模型推理、性能评估和内存评估的步骤先后顺序不固定,根据实际使用情况
决定。
4、 只有当目标平台是 Rockchip NPU 时,才可以调用 eval_memory 接口获取内存使用情况。

运行RKNN 模型时工具的使用流程

在这里插入图片描述
该场景下,首先需要完成以下两个步骤:
1、 确保开发板的 USB OTG 连接到 PC,并且正确识别到设备,即在 PC 上调用 以下命令可以查询到相关设备。

python3 -m rknn.bin.list_devices 

2、 调用 init_runtime 接口初始化运行环境时需要指定 target 参数和 device_id 参数。其中 target参数表明硬件类型,当前版本可选值为“rk1806”、“rk1808”、“rk3399pro”、“rv1109”或“rv1126”。当 PC 连接多个设备时,还需要指定 device_id 参数,即设备编号,设备编号可以通过 list_devices 接口或 python3 -m rknn.bin.list_devices 命令查询,示例如下:

all device(s) with adb mode:
[]
all device(s) with ntb mode:
[‘TB-RK1808S0’, ‘515e9b401c060c0b’]

初始化运行时环境代码示例如下:

# RK3399Pro
ret = init_runtime(target=’rk3399pro’, device_id=’VGEJY9PW7T’)

注:

  1. 目前 RK1806/RK1808/RV1109/RV1126 等设备支持 NTB 或 ADB 两种连接模式,RK3399Pro 开发板只支持 ADB 模式使用多设备时,需要确保这些设备使用相同的连接模式,即 list_devices 查询出来的设备 ID 列表都是 ADB,或都是 NTB。
  2. 在 Linux 上第一次使用 NTB 设备时,非 root 用户需要获取该 USB 设备的读写权限,这
    可以通过执行 SDK/platform-tools/update_rk_usb_rule/linux/update_rk1808_usb_rule.sh脚本完成,详细说明请参考同级目录下的 README.txt。

模型运行在 RK3399Pro Linux 开发板上

该场景下,RKNN-Toolkit 直接安装在 RK3399Pro Linux 系统中。构建或导入的 RKNN 模型直
接在 RK3399Pro 上运行,以获取模型实际的推理结果或性能信息。
对于 RK3399Pro Linux 开发板,RKNN-Toolkit 工具的使用流程取决于模型种类,如果模型类型是非 RKNN 模型,则使用流程同场景一中的第一个图;否则使用流程同第二个图。

PyTorch 模型加载接口

在这里插入图片描述
本人使用的是pytorch模型,以下是加载 pytorch模型的示例代码,如果在 PC 上执行这个例子,RKNN 模型将在模拟器上运行:

import numpy as np
import cv2
from rknn.api import RKNN
import torchvision.models as models
import torch

# 通过跟踪转换为 Torch 脚本   
# 要将 PyTorch 模型通过跟踪转换为 Torch 脚本,必须将模型的实例以及示例输入传递给torch.jit.trace函数
def export_pytorch_model():
    net = models.resnet18(pretrained=True)  # 换成你的模型
    net.eval()
    trace_model = torch.jit.trace(net, torch.Tensor(1,3,224,224))
    trace_model.save('./resnet18.pt')

# show一下输出
def show_outputs(output):
    output_sorted = sorted(output, reverse=True)
    top5_str = '\n-----TOP 5-----\n'
    for i in range(5):
        value = output_sorted[i]
        index = np.where(output == value)
        for j in range(len(index)):
            if (i + j) >= 5:
                break
            if value > 0:
                topi = '{}: {}\n'.format(index[j], value)
            else:
                topi = '-1: 0.0\n'
            top5_str += topi
    print(top5_str)


def show_perfs(perfs):
    perfs = 'perfs: {}\n'.format(perfs)
    print(perfs)


def softmax(x):
    return np.exp(x)/sum(np.exp(x))

def pytorch2rknn_predict():
	export_pytorch_model()
    model = './resnet18.pt'
    input_size_list = [[3, 224, 224]]

    # Create RKNN object
    rknn = RKNN()
	# rknn = RKNN(verbose=True, verbose_file=’./mobilenet_build.log’) # 将详细的日志信息输出到屏幕,并写到 mobilenet_build.log 文件中
	# rknn = RKNN(verbose=True)  # 只在屏幕打印详细的日志信息
    # pre-process config
    print('--> Config model')
    rknn.config(mean_values=[[123.675, 116.28, 103.53]], std_values=[[58.395, 58.395, 58.395]], reorder_channel='0 1 2')
    '''
    rknn.config(mean_values=[[103.94, 116.78, 123.68]],
					 std_values=[[58.82, 58.82, 58.82]],
					reorder_channel=’0 1 2’,
					need_horizontal_merge=True,
					target_platform=[‘rk1808’, ‘rk3399pro’])
	'''
    print('done')

    # Load Pytorch model
    print('--> Loading model')
    ret = rknn.load_pytorch(model=model, input_size_list=input_size_list)
    if ret != 0:
        print('Load Pytorch model failed!')
        exit(ret)
    print('done')

    # Build model
    print('--> Building model')
    ret = rknn.build(do_quantization=True, dataset='./dataset.txt')  # dataset.txt 是一个包含测试图片路径的文本文件
    if ret != 0:
        print('Build model failed!')
        exit(ret)
    print('done')

	# 量化精度分析
	print('--> Accuracy analysis')
	rknn.accuracy_analysis(inputs='./dataset.txt', target='rk3399pro')
	print('done')
	
    # Export RKNN model
    print('--> Export RKNN model')
    ret = rknn.export_rknn('./resnet_18.rknn')  # 导出储存为 RKNN 模型文件,用于模型部署
    if ret != 0:
        print('Export resnet_18.rknn failed!')
        exit(ret)
    print('done')
    
    # ret = rknn.load_rknn('./resnet_18.rknn')  # 改为自己的rknn模型
    # Set inputs
    img = cv2.imread('./space_shuttle_224.jpg') # 预测的图片
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    # Init runtime environment
    print('--> Init runtime environment')
    ret = rknn.init_runtime()  # ret = rknn.init_runtime(target='rk3399pro', device_id='VGEJY9PW7T')
    if ret != 0:
        print('Init runtime environment failed')
        exit(ret)
    print('done')

    # Inference
    print('--> Running model')
    outputs = rknn.inference(inputs=[img])
    show_outputs(softmax(np.array(outputs[0][0])))  # 打印结果
    print('done')

	 # perf  评估模型性能
	 print(‘→ Begin evaluate model performance’)
	 perf_results = rknn.eval_perf(inputs=[img])
	 print(‘done’)
    rknn.release()


def main():
	# export_pytorch_model()
	pytorch2rknn_predict()
	# rknn_predict()

if __name__ == '__main__':
	main()

构建 RKNN 模型APIbuild

# 构建 RKNN 模型,并且做量化
ret = rknn.build(do_quantization=True, dataset='./dataset.txt')

dataset:量化校正数据的数据集。目前支持文本文件格式,用户可以把用于校正的图片(jpg 或 png 格式)或 npy 文件路径放到一个.txt 文件中。文本文件里每一行一条路径信息。
pre_compile:预编译开关,如果设置成 True,可以减小模型大小,及模型在硬件设备上的首次启动速度。但是打开这个开关后,构建出来的模型就只能在硬件平台上运行,无法通过模拟器进行推理或性能评估。如果硬件有更新,则对应的模型要重新构建。
注:

  1. 该选项不能在 RK3399Pro Linux 开发板 / Windows PC / Mac OS X PC 上使用
  2. RKNN-Toolkit-V1.0.0 及以上版本生成的预编译模型不能在 NPU 驱动版本小于0.9.6 的设备上运行;RKNN-Toolkit-V1.0.0 以前版本生成的预编译模型不能在NPU 驱 动 版 本 大 于 等 于 0.9.6 的 设 备 上 运 行 。 驱 动 版 本 号 可 以 通 过get_sdk_version 接口查询。

加载 RKNN 模型load_rknn

# 从当前路径加载 mobilenet_v1.rknn 模型
ret = rknn.load_rknn(path='./mobilenet_v1.rknn')

参数load_model_in_npu: 是否直接加载 npu 中的 rknn 模型。其中 path 为 rknn 模型在 npu中的路径。只有当 RKNN-Toolkit 运RK3399Pro Linux 开发板或连有 NPU 设备的 PC 上时才可以设为 True。默认值为 False。

模型推理API:inference
在进行模型推理前,必须先构建或加载一个 RKNN 模型。
对当前模型进行推理,返回推理结果。
如果 RKNN-Toolkit 运行在 PC 上,且初始化运行环境时设置 target 为 Rockchip NPU设备,得到的是模型在硬件平台上的推理结果。
如果 RKNN-Toolkit 运行在 PC 上,且初始化运行环境时没有设置 target,得到的是模型在模拟器上的推理结果。模拟器可以模拟 RK1808,也可以模拟 RV1126,具体模拟哪款芯片,取决于 RKNN 模型的 target_platform 参数值.
如果 RKNN-Toolkit 运行在 RK3399Pro Linux 开发板上,得到的是模型在实际硬件上的推理结果。
data_format:数据模式,可以填以下值: “nchw”, “nhwc”。默认值为’nhwc’。这两个的不同之处在于 channel 放置的位置。

评估模型性能API: eval_perf

# 对模型性能进行评估
……
rknn.eval_perf(inputs=[image], is_print=True)
……

评估模型性能。
模型运行在 PC 上,初始化运行环境时不指定 target,得到的是模型在模拟器上运行的性能数据,包含逐层的运行时间及模型完整运行一次需要的时间。模拟器可以模拟RK1808,也可以模拟 RV1126,具体模拟哪款芯片,取决于 RKNN 模型的 target_platform参数值。
模型运行在与 PC 连接的 Rockchip NPU 上,且初始化运行环境时设置 perf_debug 为 False,则获得的是模型在硬件上运行的总时间;如果设置 perf_debug 为 True,除了返回总时间外,还将返回每一层的耗时情况。
模型运行在 RK3399Pro Linux 开发板上时,如果初始化运行环境时设置 perf_debug 为 False,获得的也是模型在硬件上运行的总时间;如果设置 perf_debug 为 True,返回总时间及每一层的耗时情况

量化精度分析API:accuracy_analysis
使用浮点和量化模型推理并将每一层的结果做快照。之后再根据快照里的数据,比较量化模型和浮点模型每一层的差距,用于评估量化所产生的误差或错误。
注:

  1. 该接口只能在 buildhybrid_quantization_step1 之后调用,并且原始模型应
    该为非量化的模型,否则会调用失败。
    45
  2. 该接口使用的量化方式与 config 中指定的一致。
rknn.accuracy_analysis(inputs='./dataset.txt', target='rk3399pro')

导出加密模型API: export_encrypted_rknn_model
该接口的功能是将普通的 RKNN 模型按一定的算法进行加密。
注:

  1. 加密后的 RKNN 模型,使用方法同普通模型。
  2. 加密后的 RKNN 模型,如果使用 Python 接口部署,要注意 target 不能是模拟器;如果使用 C API 进行部署,则只要把 RKNN 模型更换即可,其他代码不用做修改。

input_model: 待加密的 RKNN 模型路径。数据类型为字符串。必填参数。
output_model: 模型加密后的保存路径。数据类型为字符串。选填参数,如果不填该参数,则使用{original_model_name}.crypt.rknn 作为加密后的模型的名字。
crypt_level: 加密等级。等级越高,安全性越高,解密越耗时;反之,安全性越低,解密越快。数据类型为整型,默认值为 1,目前安全等级有 3 个等级,1,2 和 3。

from rknn.api import RKNN
if __name__ == '__main__':
 rknn = RKNN()
 ret = rknn.export_encrypted_rknn_model('test.rknn')
 if ret != 0:
	 print('Encrypt RKNN model failed.')
	 exit(ret)
 rknn.release()

获取设备列表API:list_devices
列出已连接的 RK3399PRO/RK1808/RV1109/RV1126 或 TB-RK1808 AI 计算棒。
注:目前设备连接模式有两种:ADB 和 NTB。其中 RK3399PRO 目前只支持 ADB 模式,TB-RK1808 AI 计算棒只支持 NTB 模式,RK1808/RV1109 支持 ADB/NTB 模式。多设备连接时请确保他们的模式都是一样的。
返回 adb_devices 列表和 ntb_devices 列表,如果设备为空,则返回空列表。例如我们的环境里插了两个 TB-RK1808 AI 计算棒,得到的结果如下:

adb_devices = []
ntb_devices = ['TB-RK1808S0', '515e9b401c060c0b']
from rknn.api import RKNN
if __name__ == '__main__':
 rknn = RKNN()
 rknn.list_devices()
 rknn.release()

返回的设备列表信息如下(这里有两个 RK1808 开发板,它们的连接模式都是 adb):

*************************
all device(s) with adb mode:
['515e9b401c060c0b', 'XGOR2N4EZR']
*************************

查询模型可运行平台API: list_support_target_platform
查询给定 RKNN 模型可运行的芯片平台。
rknn_model:RKNN 模型路径。如果不指定模型路径,则按类别打印 RKNN-Toolkit当前支持的芯片平台。
support_target_platform: Returns runnable chip platforms, or None if the model path is empty.

rknn.list_support_target_platform(rknn_model=’mobilenet_v1.rknn’)

结果展示:

**************************************************
Target platforms filled in RKNN model: []
Target platforms supported by this RKNN model: ['RK1806', 'RK1808', 'RK3399PRO']
**************************************************
  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值