Open liuqinglong110 opened 4 weeks ago
inputs[0].size = app_ctx.model_channel 300 2 * 8; 这个size是什么意思? 第一个参数的通道数是几?后面为什么要乘以8?
inputs[0].size = app_ctx.model_channel 300 2 * 8; 这个size是什么意思? 第一个参数的通道数是几?后面为什么要乘以8?
第一个问题:这个inputs[0]是为了给rknn_inputs_set()函数准备的输入,input[0].size表示的是第0个输入数据所占内存的大小。 我参考了《02_Rockchip_RKNPU_User_Guide_RKNN_SDK_V2.2.0_CN.pdf》文档的第80页,仿照推理代码示例写的: 另外,我还在其他地方找了相似的写法 https://www.easy-eai.com/document_details/18/614#3.7%20rknn_run 具体写法: 第二个问题:第一个参数的通道数,我设置成了1。我截图的图片中有打印:app_ctx.model_channel === :1 我的模型输入有四个输入,都不是图片类型。四个参数分别是两张图片中特征点的坐标,都是300个点:(300, 2)、(300, 2)),另外两个输入分别是对应的图片的特征描述子,维度是:(300, 256)、(300, 256)。转换模型之后,rknn中显示如下: 第三个问题:最后乘以8是由于代码在板端运行报错,我自己试了几次,应该是申请的内存大小与输入变量大小不匹配。一般会出现如下错误: 而且我还观察到,我的模型四个输入是fp16,因为我没有进行int8量化。乘以8,也和我设置inputs[0].type = RKNN_TENSOR_FLOAT32;的数据类型有关系。 这里我有些混乱了。
你设置的输入类型是fp32,那么你输入的数组应该是float的,对于第一个输入,他的size应该是13002*4的,passthrough=0是正确的,sdk内部会把你输入的fp32转成fp16;或者你自己在外边输入fp16的数据,此时passthrough设置为1,表示直接给模型你的数据,不要进行转换
你设置的输入类型是fp32,那么你输入的数组应该是float的,对于第一个输入,他的size应该是1_300_2*4的,passthrough=0是正确的,sdk内部会把你输入的fp32转成fp16;或者你自己在外边输入fp16的数据,此时passthrough设置为1,表示直接给模型你的数据,不要进行转换
嗯嗯。我尝试把fp32的数据转成fp16,问题太多,还是继续使用fp32作为原始输入类型吧。我已经改成了13002*4。 其中,在把输入数据赋值给inputs[0].buf之前,我的归一化函数normalize_keypoints()已经把坐标点都处理成了fp32类型。归一化之后的数据,我都和python的rknnlite2对比过了,数据也是相同的。甚至我检查了inputs[0].buf、inputs[1].buf、inputs[2].buf、inputs[3].buf被赋值之后的数据,也都是符合要求的。还是没有排查出来到底哪个步骤出了问题。
归一化函数如下: // 归一化关键点坐标的函数
Eigen::MatrixXf normalize_keypoints(const Eigen::MatrixXf &kpts, int h, int w)
{
// std::cout << "kpts: " << kpts << std::endl;
Eigen::Vector2f size(w, h);
Eigen::Vector2f shift = size / 2;
float scale = shift.maxCoeff();
// std::cout << "shift: " << shift << std::endl;
// std::cout << "scale: " << scale << std::endl;
Eigen::MatrixXf normalized_kpts = (kpts.array().rowwise() - shift.transpose().array()) / scale;
// std::cout << "normalized_kpts: " << normalized_kpts << std::endl;
return normalized_kpts;
}
Eigen::Map<const Eigen::MatrixXf> scores(scores_buf, 1, 300 * 300); // 映射为 (1, 90000) 矩阵
改成这样试试?
(1, 90000)
改成如下代码: 运行结果好像没有什么变换: c++代码的运行结果在绝对值上总是和rknnlite2的结果差4倍左右,所有,我感觉是不是还是和数据类型有关系。
很奇怪啊,lite底层也是用的so库,怎么会结果不一样...肯定是自己写的c++的输入或者输入配置和python的不一样
@liuqinglong110 你好,想问下您那边rknnlite2和C++推理,两者除了精度不一致,速度一样吗?C++是否可以提升效率呢?
@liuqinglong110 你好,想问下您那边rknnlite2和C++推理,两者除了精度不一致,速度一样吗?C++是否可以提升效率呢?
你好。我看前面@yuyun2000的回复,“lite底层也是用的so库”,理论上和c++推理速度一样的,我没有详细的比较。因为后处理很多矩阵运算,我自己用c++和eigen库实现后,执行效率太低,反倒不如直接在rk3588上用lite跑Python代码。我最后就是用Python跑lite。
@liuqinglong110 你好,想问下您那边rknnlite2和C++推理,两者除了精度不一致,速度一样吗?C++是否可以提升效率呢?
你好。我看前面@yuyun2000的回复,“lite底层也是用的so库”,理论上和c++推理速度一样的,我没有详细的比较。因为后处理很多矩阵运算,我自己用c++和eigen库实现后,执行效率太低,反倒不如直接在rk3588上用lite跑Python代码。我最后就是用Python跑lite。
哦哦,那如果速度差不多的话,用rknnlite推理应该也是一样的。我给你发邮箱,咱们交流吧~
说悄悄话是吧
说悄悄话是吧
大神,那我咨询下您吧,rknnlite2和c++推理的底层是同一个库吗?他们推理效率是否一致呀?
python是用的so库的接口,纯推理的速度是一样的,前后处理肯定是c的效率更高
python是用的so库的接口,纯推理的速度是一样的,前后处理肯定是c的效率更高
好的好的,感谢呀
说悄悄话是吧
哈哈哈,大佬误会了。他们可能是感觉现在交流效率太低了,比较着急。我工作时间也不太可能聊微信的。我们还是在这里讨论。大佬有空的时候,可以帮我们指导指导。
佬,我想请教个问题。lightglue的onnx中存在NonZero算子,无法转为RKNN格式。这里您是通过自定义算子的方式实现转换的吗?
佬,我想请教个问题。lightglue的onnx中存在NonZero算子,无法转为RKNN格式。这里您是通过自定义算子的方式实现转换的吗?
不支持的算子操作,你在导出onnx的时候,把它拿出网络就行了。放到后处理中。
佬,我想请教个问题。lightglue的onnx中存在NonZero算子,无法转为RKNN格式。这里您是通过自定义算子的方式实现转换的吗?
不支持的算子操作,你在导出onnx的时候,把它拿出网络就行了。放到后处理中。
感谢佬的回复。目前看来也只有这种方法才最方便了。
还有一个办法也很方便啊,你把不支持的模型用onnx跑就可以了,不用自己实现c++算子,而且你实现的也不一定比onnx快
还有一个办法也很方便啊,你把不支持的模型用onnx跑就可以了,不用自己实现c++算子,而且你实现的也不一定比onnx快
大佬,rknn toolkit lite什么时候能够支持自定义算子
估计没希望吧,rknnlit为啥要支持自定义,rknnlite直接用python环境加载onnx模型不就可以了吗?
您好! superpoint_lightglue.rknn可以分享一下吗, 我从onnx转rknn 总是失败
您好,我正在把lightGlue模型移植到RK3588板端,目前使用rknnlite2的Python脚本在板端推理符合预期。但是使用c++代码推理同样的模型时,直接得到的输出结果与rknnlite2的Python脚本结果差异较大。
以下是我的详细操作: 1、从onnx转换成rknn模型后,输入输出维度如下所示:有四个输入,一个输出。 转换rknn模型时,设置了QUANTIZE_ON = False # 设置为False时,表示将原始模型转成 fp16。 2、在rk3588板端,使用rknnlite2的python脚本推理,运行结果正确。具体代码如下所示: `import cv2
import torch
import numpy as np import matplotlib import matplotlib.pyplot as plt from rknnlite.api import RKNNLite from typing import List, Optional, Union
rknn_model = './model/RK3588/superpoint_lightglue.rknn'
def normalize_keypoints(kpts: np.ndarray, h: int, w: int) -> np.ndarray: size = np.array([w, h]) shift = size / 2 scale = size.max() / 2 kpts = (kpts - shift) / scale return kpts.astype(np.float32)
读取数据的函数,处理带逗号的文件并增加类型转换为 int64 或 float32
def load_from_txt(filepath, shape, dtype=np.int64):
使用 np.genfromtxt 读取,指定逗号为分隔符
if name == 'main':
最后,scores[0]输出结果: 3、使用c++代码在板端实现推理,具体推理代码: 初始化代码: ` bool init(SegRgbParams ¶ms) { rknn_context ctx;
推理代码:
cv::Mat lightGlue(uint32_t img_width, uint32_t img_height, uint8_t *data, uint64_t img_channels, std::vector}` c++代码推理结果:最后的scores输出结果与rknnlite2结果相差较大。
目前,我已经对比验证了rknnlite2和c++代码的输入数据,包括数据输入给模型之前的归一化结果。两套代码中的归一化结果也是完全一样的,也就是说从开始输入rknn的api之前数据都一致。那么基本上就确定是c++代码的问题了。 请您帮忙看看问题可能出现在哪里了?