赞
踩
对于不同的芯片,需要不同的工具:
RKNN-Toolkit1 v1.7.1 (for RK3399pro/RK1808/RV1126/RV1109)
工具:https://github.com/rockchip-linux/rknn-toolkit
RKNN-Toolkit2 v1.3 (for RK356x/RK3588/RV1106)
工具: https://github.com/rockchip-linux/rknn-toolkit2
在rknn-toolkit/examples/的目录下有各种格式的模型转换为rknn模型的例子,照着例子改就行。
也可以从百度磁盘下载rknn-toolkit的DOCKER,里面包含了所有的github的代码及转换模型的环境https://eyun.baidu.com/s/3bqbs86j
提取码:rknn
是float16的。
对于rknn输出的数据,可以使用如下的代码在float16和float32之间进行转换。
void __f32_to_f16(uint16_t* f16, float* f32, int num) { float* src = f32; uint16_t* dst = f16; int i = 0; for (; i < num; i++) { float in = *src; uint32_t fp32 = *((uint32_t *) &in); uint32_t t1 = (fp32 & 0x80000000u) >> 16; /* sign bit. */ uint32_t t2 = (fp32 & 0x7F800000u) >> 13; /* Exponent bits */ uint32_t t3 = (fp32 & 0x007FE000u) >> 13; /* Mantissa bits, no rounding */ uint32_t fp16 = 0u; if( t2 >= 0x023c00u ) { fp16 = t1 | 0x7BFF; /* Don't round to infinity. */ } else if( t2 <= 0x01c000u ) { fp16 = t1; } else { t2 -= 0x01c000u; fp16 = t1 | t2 | t3; } *dst = (uint16_t) fp16; src ++; dst ++; } } void __f16_to_f32(float* f32, uint16_t* f16, int num) { uint16_t* src = f16; float* dst = f32; int i = 0; for (; i < num; i++) { uint16_t in = *src; int32_t t1; int32_t t2; int32_t t3; float out; t1 = in & 0x7fff; // Non-sign bits t2 = in & 0x8000; // Sign bit t3 = in & 0x7c00; // Exponent t1 <<= 13; // Align mantissa on MSB t2 <<= 16; // Shift sign bit into position t1 += 0x38000000; // Adjust bias t1 = (t3 == 0 ? 0 : t1); // Denormals-as-zero t1 |= t2; // Re-insert sign bit *((uint32_t*)&out) = t1; *dst = out; src ++; dst ++; } }
转换caffe模型的时候遇到错误:
这个是因为caffe模型的头部格式和rknn的默认格式不兼容。比如我的模型文件头部是:
name: "xxxx"
input: "data"
input_shape: { dim: 1 dim: 3 dim: 640 dim: 640 }
改为下面的格式就好了:
layer {
name: "data"
type: "Input"
top: "data"
input_param {
shape {
dim: 1
dim: 3
dim: 640
dim: 640
}
}
}
在板子上运行rknn模型,遇到错误:
This RKNN model is not a pre-compiled model, but the npu driver is mini driver.
Mini driver only support rknn models with pre-compiled mode.
Create RKNN model fail, error=-14
rknn_init error ret=-14
意思也很直白,我板子上的库是Mini driver, 所以只能加载预编译的模型,在转换模型的时候,打开预编译开关precompile:
rknn.config(mean_values=[[0, 0, 0]], std_values=[[1, 1, 1]], reorder_channel='2 1 0', pre_compile=True)
运行时遇到错误:
E [op_optimize:428]CONCAT, uid 181 must have same quantize parameter!
同时,demsg中也有错误信息:
[galcore]: GPU[0] hang, automatic recovery.
这个问题我在rknn的技术群里咨询了, rknn1.7之后的版本对这个问题有较好的解决,只要升级板子上的rknn库和驱动就行了。
rknn的驱动和更新方法:https://github.com/rockchip-linux/rknpu
所谓更新驱动,就是把库拷贝到板子上。
接上个问题,官方问题里似乎把rknn的动态库称为用户态驱动,所以在文档里看到更新驱动不能只更新ko文件,so文件也要一起更新。
这个不一定,要看看模型加载后读取的tensor属性。以我的一个模型举例,目标检测模型转换后,bbox坐标是uint8的,但是分类置信度是float16的,需要用到本文上面提到的float16转float32的函数提取数据。
static float deqnt_affine_to_f32(int8_t qnt, int32_t zp, float scale)
{
return ((float)qnt - (float)zp) * scale;
}
在板子上,在命令行上执行"export NN_LAYER_DUMP=1",然后运行程序执行网络推理,最后一层的数据就会dump到当前目录。
如果是在PC上用python评估rknn模型,在命令行上执行"export NN_LAYER_DUMP=1",之后运行模型,则会在当前目录输出大部分网络层的数据。
dump的数据基本都是float类型的,不用再反量化了。
转换模型时可以将rknn.config的reorder_channel设置为’2 1 0’。
rknn.config(mean_values=[[0, 0, 0]], std_values=[[1, 1, 1]], reorder_channel='2 1 0', precompile=True)
NHWC
不需要,只要在input的fmt设置为图片真实的格式, rknn的库就会自动处理这种转换
inputs[0].fmt = RKNN_TENSOR_NHWC;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。