|
本帖最后由 NeonEcho 于 2025-10-16 17:02 编辑
平台:RK3588
NPU:2.2
driver:0.9.2
1. 起因是rknn_input_set接口耗时比较长(2ms),后面查到pass_through=0,也就是rknn内部帮助进行了预处理工作,于是我想自己进行预处理,将pass_through置为1;
2.查阅官方文档,发现rknn_input_set可能会做三个操作:类型转换,归一化,量化,按照这个思路进行预处理
3. 该模型在量化的时候,采用混合量化,rknn.config没有配置均值和方差,即没有归一化操作
- 量化代码:
- rknn.config(mean_values=None, std_values=None, target_platform="rk3588",
- quantized_algorithm="mmse",
- quantized_method='channel',
- optimization_level=3)
- ret = rknn.load_onnx(model=ONNX_MODEL,
- input_size_list=[[3, 127, 127], [3, 255, 255]])
- ret = rknn.build(do_quantization=QUANTIZE_ON, dataset=DATASET)
- ret = rknn.export_rknn(RKNN_MODEL)
4. 该模型输入为FP16数据,输入数据分布为NHWC,但是没有进行量化
- <font color="#ff00ff">query输出:</font>
- index=0, name=input_z, n_dims=4, dims=[1, 127, 127, 3], n_elems=48387, size=96774, fmt=NHWC, type=FP16, qnt_type=AFFINE, zp=0, scale=1.000000
- index=1, name=input_x, n_dims=4, dims=[1, 255, 255, 3], n_elems=195075, size=390150, fmt=NHWC, type=FP16, qnt_type=AFFINE, zp=0, scale=1.000000
5. 也就是说,我只需要将输入改为FP16即可,这里为了方便对比,我把pass_through=0时的代码也放出来
pass_through = 0:
- v3_input[i].index = i;
- v3_input[i].type = RKNN_TENSOR_UINT8;
- v3_input[i].size = width_v3[i] * height_v3[i] * channel_v3[i] * sizeof(uint8_t);
- v3_input[i].fmt = RKNN_TENSOR_NHWC;
- v3_input[i].pass_through = 0;
- v3_input[1].buf = (void*)x_crop.data; // x_crop和z_mat是imread读取的CV_8UC3数据,未作处理
- v3_input[0].buf = (void*)z_mat.data;
- rknn_inputs_set(v3_ctx, v3_io_num.n_input, v3_input);
pass_through = 1:- v3_input[i].index = i;
- v3_input[i].type = RKNN_TENSOR_FLOAT16;
- v3_input[i].size = width_v3[i] * height_v3[i] * channel_v3[i] * sizeof(float16_t);
- v3_input[i].fmt = RKNN_TENSOR_NHWC;
- v3_input[i].pass_through = 1;
- x_crop.convertTo(x_crop, CV_16FC3, 1.0); // 多了类型转换
- z_mat.convertTo(z_mat, CV_16FC3, 1.0);
- v3_input[1].buf = (void*)x_crop.data; // x_crop和z_mat是imread读取的CV_8UC3数据,未作处理
- v3_input[0].buf = (void*)z_mat.data;
- rknn_inputs_set(v3_ctx, v3_io_num.n_input, v3_input);
但是输出的数据却不一致,pass_through = 1输出的是错的
- 26.7188 31.6562 36.5 43.0312 50.7812 53.0312 43.1875 41.6875 43.6875 // pass_through = 0
- 27.6094 34.0312 39.625 44.3125 44.75 47.0625 47.7188 49.125 49.8125 // pass_through = 1
虽然数值上差距不大,但是应用上的结果全是错的。
6. 我又进一步做了对比,这次将输入数据设为全0或全255,全0是两次结果一样,符合预期,因为所有的处理对全0都无效了;但是全255的结果就不一样了,这样可以暂时排除通道错误或者颜色错误这种问题,所以应该还是rknn_input_set内部做了什么数值修改的操作
希望版主能帮忙看一下,这个问题已经困扰好几天了,不胜感激。
|
|