模型在rv1126上跑起来遇到的坑

2024-05-25 23:58
文章标签 模型 遇到 起来 rv1126

本文主要是介绍模型在rv1126上跑起来遇到的坑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

rknn对模型是彩色图片输入的很友好,如果输入是灰度图片,需要好好理解它的整套数据处理流程。
在这里插入图片描述
上面是数据处理的整个流程,cpu拿到的图片数据,需要经过一系列的预处理(颜色通道转换,归一化,量化,通道转换)这一过程是在rknn_inputs_set里面完成。
我的模型信息:
在这里插入图片描述
模型输入1个,单通道,数据类型是uint8, 量化类型为asymmetric affine非对称量化,即float32和uint8之间的转换。fl zp scale都是量化的参数。
在这里插入图片描述
模型输出2个,一个数据类型为float16 没有量化
第二个类型为uint8, 量化类型为asymmetric affine.

rknn_inputs_set耗时严重

我碰到的问题就是rknn_inputs_set非常的耗时!大概33ms左右!我是单通道图片,1400640,fmt是NCHW,也就是需要进行中间两步即可。先归一化成float32,再量化为uint8,然后把数据从cpu拷贝到npu,不知道为啥耗时这么长。最后问了rk的工作人员,说是对彩色图片内部做了优化,而灰度图片没有。
所以只能自己做优化。
rk的文档提供了两种方式:
1.是rknn_inputs_set里设置pass_through=1,相当于数据不再需要rknn_inputs_set做预处理,我自己处理好。我理解的这种应该是只节省了预处理的时间,拷贝的时间是仍然需要的。我之前自己实现了归一化和量化步骤(官网也有demo),耗时在10ms左右。后来我仔细阅读文档,发现如果三通道均值和方差相同,则输入 uint8 数据等于归一化后量化的 uint8 数据。
在这里插入图片描述
所以我的归一化和量化是可以省略的,也就是中间两步也省了,图片原始数据直接透传给NPU。这时rknn_inputs_set变成了1ms左右!我理解的拷贝耗时呢???
2.第二种是零拷贝,即把拷贝也省了。官方给了很详细的demo。原理大概是在内核核申请一片内存,数据放到这片内存上,npu直接去拿。不需要从cpu拷贝到npu。

rknn_outputs_set耗时

我已经设置了output_optimize=1,耗时在14ms左右,耗时主要是因为第二个输出,需要从uint8变为float32。
为了解决这个问题,我决定自己在外面做反量化。
反量化比量化简单很多,就是((float)qnt - (float)zp) * scale 我的模型第二个输出zp = 136 scale = 4.625256.

验证结果:
按照uint8_t直接把结果拿出来:

outputs[1].want_float = 0;
uint8_t* pdes = (uint8_t*)outputs[1].buf;
cv::Mat des_mat(400/8 * 256, 640/8, CV_8UC1, pdes);
std::cout << "des " << des_mat << std::endl;

输出结果:
在这里插入图片描述
耗时变成8ms。
按照float把结果拿出来:

outputs[1].want_float = 1;
float* pdes = (float*)outputs[1].buf;
cv::Mat des_mat(400/8 * 256, 640/8, CV_32FC1, pdes);
std::cout << "des " << des_mat << std::endl;

输出结果:
在这里插入图片描述
耗时19ms。
拿第一个做反量化运算:(124-136)* 4.625256 = −55.503072 恰好等于float拿出来的结果。所以这种方式是ok。

注意opencv恰好有数据类型转换的函数convertTo

/** @brief Converts an array to another data type with optional scaling.The method converts source pixel values to the target data type. saturate_cast\<\> is applied atthe end to avoid possible overflows:\f[m(x,y) = saturate \_ cast<rType>( \alpha (*this)(x,y) +  \beta )\f]@param m output matrix; if it does not have a proper size or type before the operation, it isreallocated.@param rtype desired output matrix type or, rather, the depth since the number of channels are thesame as the input has; if rtype is negative, the output matrix will have the same type as the input.@param alpha optional scale factor.@param beta optional delta added to the scaled values.*/void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;

只需要转换一下参数即可。代码如下:

    uint8_t* pdes = (uint8_t*)outputs[1].buf;cv::Mat des_mat(400/8 * 256, 640/8, CV_8UC1, pdes);cv::Mat des;des.convertTo(des, CV_32FC1, 4.625256, -136*4.625256);

其实第一个输出也可以做类似的工作,模型的输出是float16, 我们可以自己在外面转为float32,(32 位浮点 和16 位浮点数相互转换 请参考 IEEE-754标准)。我看了一下,第一个也outputs[1].want_float = 0;模型输出耗时为4ms,测试convertTo的耗时为3.6855。加上第一个输出convertTo的耗时,和rk内部转换耗时8ms差不多,可以不采用自己转换。而计算描述子是放在后端5hz的,我们可以把第二个输出的convertTo到后端,不计入整个提点耗时里面。
故第一个输出采用want_float = 1,由rk内部转换;第二个采用want_float = 0,自己转换;

输出结果和在电脑的输出差异很大

应该是量化带来的误差。
1.首先确保 float 类型的精度和原始平台测试结果相近,rknn.build(do_quantization=False)
结果如下:
在电脑跑出来的结果
在这里插入图片描述
没有量化的结果
在这里插入图片描述
可见结果还是比较相近,误差在百分位上面。
2.测试量化后的精度
在这里插入图片描述
明显已经误差很大了,我用的图片数量10张,文档建议给出大于200张图片。
结果还是还上面一样
在这里插入图片描述
结果还是和上面一样,说明不是图片量太少的问题,需要分析每一层的量化精度。
rknn.accuracy_analysis(inputs='./image/dataset1.txt', target='rv1126')分析。
首先找到每一层对应的npu表示术语。

x = self.relu(self.conv1a(data))convolution_at_input0.1_1_1_out0_nhwc_1_400_640_64.tensor relu_at_89_2_2_out0_nhwc_1_400_640_64.tensor
x = self.relu(self.conv1b(x))convolution_at_input.3_3_3_out0_nhwc_1_400_640_64.tensor relu_at_101_4_4_out0_nhwc_1_400_640_64.tensor
x = self.pool(x)max_pooling_at_input.4_5_5_out0_nhwc_1_200_320_64.tensor
x = self.relu(self.conv2a(x))convolution_at_input.5_6_6_out0_nhwc_1_200_320_64.tensor relu_at_122_7_7_out0_nhwc_1_200_320_64.tensor
x = self.relu(self.conv2b(x))convolution_at_input.6_8_8_out0_nhwc_1_200_320_64.tensor relu_at_134_9_9_out0_nhwc_1_200_320_64.tensor
x = self.pool(x)max_pooling_at_input.7_10_10_out0_nhwc_1_100_160_64.tensor
x =self.relu(self.conv3a(x))convolution_at_input.8_11_11_out0_nhwc_1_100_160_128.tensor relu_at_155_12_12_out0_nhwc_1_100_160_128.tensor
x = self.relu(self.conv3b(x))convolution_at_input.9_13_13_out0_nhwc_1_100_160_128.tensor relu_at_167_14_14_out0_nhwc_1_100_160_128.tensor
x = self.pool(x)max_pooling_at_input.10_15_15_out0_nhwc_1_50_80_128.tensor
x = self.relu(self.conv4a(x))convolution_at_input.11_16_16_out0_nhwc_1_50_80_128.tensor relu_at_188_17_17_out0_nhwc_1_50_80_128.tensor
x = self.relu(self.conv4b(x))convolution_at_input.12_18_18_out0_nhwc_1_50_80_128.tensor relu_at_200_19_19_out0_nhwc_1_50_80_128.tensor

之后就是分开部分了,由于我们只关心描述子,就只看描述子部分的。

cDa = self.relu(self.convDa(x))convolution_at_input.1_40_34_out0_nhwc_1_50_80_256.tensor relu_at_235_41_35_out0_nhwc_1_50_80_256.tensor
descriptors = self.convDb(cDa)convolution_at_246_43_37_out0_nhwc_1_50_80_256.tensor

这篇关于模型在rv1126上跑起来遇到的坑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1002979

相关文章

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

在MySQL执行UPDATE语句时遇到的错误1175的解决方案

《在MySQL执行UPDATE语句时遇到的错误1175的解决方案》MySQL安全更新模式(SafeUpdateMode)限制了UPDATE和DELETE操作,要求使用WHERE子句时必须基于主键或索引... mysql 中遇到的 Error Code: 1175 是由于启用了 安全更新模式(Safe Upd

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

Spring AI Alibaba接入大模型时的依赖问题小结

《SpringAIAlibaba接入大模型时的依赖问题小结》文章介绍了如何在pom.xml文件中配置SpringAIAlibaba依赖,并提供了一个示例pom.xml文件,同时,建议将Maven仓... 目录(一)pom.XML文件:(二)application.yml配置文件(一)pom.xml文件:首

解决JavaWeb-file.isDirectory()遇到的坑问题

《解决JavaWeb-file.isDirectory()遇到的坑问题》JavaWeb开发中,使用`file.isDirectory()`判断路径是否为文件夹时,需要特别注意:该方法只能判断已存在的文... 目录Jahttp://www.chinasem.cnvaWeb-file.isDirectory()遇

如何在本地部署 DeepSeek Janus Pro 文生图大模型

《如何在本地部署DeepSeekJanusPro文生图大模型》DeepSeekJanusPro模型在本地成功部署,支持图片理解和文生图功能,通过Gradio界面进行交互,展示了其强大的多模态处... 目录什么是 Janus Pro1. 安装 conda2. 创建 python 虚拟环境3. 克隆 janus

本地私有化部署DeepSeek模型的详细教程

《本地私有化部署DeepSeek模型的详细教程》DeepSeek模型是一种强大的语言模型,本地私有化部署可以让用户在自己的环境中安全、高效地使用该模型,避免数据传输到外部带来的安全风险,同时也能根据自... 目录一、引言二、环境准备(一)硬件要求(二)软件要求(三)创建虚拟环境三、安装依赖库四、获取 Dee

DeepSeek模型本地部署的详细教程

《DeepSeek模型本地部署的详细教程》DeepSeek作为一款开源且性能强大的大语言模型,提供了灵活的本地部署方案,让用户能够在本地环境中高效运行模型,同时保护数据隐私,在本地成功部署DeepSe... 目录一、环境准备(一)硬件需求(二)软件依赖二、安装Ollama三、下载并部署DeepSeek模型选

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

mysql主从及遇到的问题解决

《mysql主从及遇到的问题解决》本文详细介绍了如何使用Docker配置MySQL主从复制,首先创建了两个文件夹并分别配置了`my.cnf`文件,通过执行脚本启动容器并配置好主从关系,文中还提到了一些... 目录mysql主从及遇到问题解决遇到的问题说明总结mysql主从及遇到问题解决1.基于mysql