SOPHON OpenCV中Mat是如何分配设备内存和系统内存及相关问题

SOPHON OpenCV中Mat是如何分配设备内存和系统内存的

因为受设计影响,这个问题细节比较多,主要从三方面能解释。

  1. 在SoC模式下,设备内存和系统内存是同一份物理内存,通过操作系统的ION内存进行管理,系统内存是ION内存的mmap获得。在pcie模式下,设备内存和系统内存是两份物理内存,设备内存指BM168x卡上的内存,系统内存指服务器上操作系统内存。如果用户想只开辟系统内存,和开源opencv保持一致,可 以参见FAQ26的回答。

  2. 在Sophon OpenCV中默认会同时开辟设备内存和系统内存,其中系统内存放在mat.u->data或mat.data中,设备内存放在mat.u->addr中。只有以下几种情况会不开辟设备内存,而仅提供系统内存:

    • 当data由外部开辟并提供给mat的时候。即用以下方式声明的时候:
      Mat mat(h, w, type, data); 或 mat.create(h, w, type, data);

    • 在SoC模式下,当type不属于(CV_8UC3, CV_32FC1, CV_32FC3)其中之一的时候。这里特别注意CV_8UC1是不开辟的,这是为了保证我们的opencv能够通过开源opencv的opencv_test_core的一致性验证检查。

    • 当宽或者高小于16的时候。因为这类宽高,硬件不支持

  3. 在BM1682和BM1684的SoC模式下,mat分配的CV_8UC3类型的设备内存会自动做64对齐,即分配的内存大小一定是64对齐的(注意:仅对SoC模式的CV_8UC3而言,且仅对BM1684/BM1682芯片)。在PCIE模式下,分配的内存是byte对齐的。

相关问题:

1. OpenCV中默认是使用ION内存作为MAT的data空间,如何指定Mat对象基于system memory内存去创建使用

using namespace cv;
Mat m;
m.allocator = m.getDefaultAllocator();     // get system allocator

然后就可以正常调用各种mat函数了,如m.create() m.copyto(),后面就会按照指定的allocator来分配内存了

m.allocator = hal::getDefaultAllocator();  // get ion allocator

就又可以恢复使用ION内存分配器来分配内存。

2. 在SoC模式下,OpenCV在使用8UC1 Mat的时候报错,而当Mat格式为8UC3的时候,同样的程序完全工作正常:

在SoC模式下,默认创建的8UC1 Mat是不分配设备内存的。因此当需要用到硬件加速的时候,比如推理,bmcv操作等,就会导致各种内存异常错误。

参考问题 1. 指定8UC1 Mat在创建的时候,内部使用ion分配器去分配内存。如下所示:

cv::Mat gray_mat;
gray_mat.allocator = hal::getAllocator();
gray_mat.create(h, w, CV_8UC1);

3. SoC模式使用cv::Mat的数据地址初始化另外一个cv::Mat时有可能会出现乱码

SoC模式使用cv::Mat的数据地址初始化另外一个cv::Mat 时需要指定_step,即

cv::Mat image_temp_1(image_ost.rows,image_ost.cols,CV_8UC3,image_ost.data,image_ost.step[0]);

4. SoC模式对cv::Mat的内存进行操作

SoC模式下面,cv::Mat的内存需要64字节对齐,所以cv::Mat的内存长度不是width3height,而是stepheight,如果原始图像满足64字节对齐,那么step=width3

5. Mat创建失败,提示“terminate called after throwing an instance of ‘cv::Exception’ what(): OpenCV(4.1.0) …… matrix.cpp:452: error: (-215:Assertion failed) u != 0 in function ‘creat’”

这种错误主要是设备内存分配失败。失败的原因有两种:

  1. 句柄数超过系统限制,原因有可能是因为句柄泄漏,或者系统句柄数设置过小,可以用如下方法确认:
    查看系统定义的最大句柄数:
    ulimit -n
    
    查看当前进程所使用的句柄数:
    lsof -n|awk{print $2}|sort|uniq -c|sort -nr|more
    
  2. 设备内存不够用。可以用如下方法确认:
    SOC模式下:
    cat /sys/kernel/debug/ion/bm_vpp_heap_dump/summary
    
    PCIE模式下:
    bm-smi工具可以查看设备内存空间

解决方案:

在排除代码本身的内存泄漏或者句柄泄漏问题后,可以通过加大系统最大句柄数来解决句柄的限制问题:ulimit -HSn 65536
设备内存不够就需要通过优化程序来减少对设备内存的占用,或者通过修改dts文件中的内存布局来增加对应的设备内存。详细可以参考SM5用户手册中的说明。

6. 用已有Mat的内存数据的宽高去创建新的Mat后,新Mat保存的图像数据错行导致显示不正常

保存的图像错行,通常是由于Mat中step信息丢失所造成。
一般用已有Mat去生成一个新Mat,并且要求内存复用时,可以直接赋值给新的Mat来简单实现,如 Mat1 = Mat2.

但在某些情况下,比如有些客户受限于架构,函数参数只能用C风格的指针传递,就只能用Mat中的data指针,rows,cols成员来重新恢复这个Mat。 这时候就需要注意step变量的设置,在默认情况下是AUTO_STEP配置,即每行数据没有填充数据。但是在很多种情况下,经过opencv处理后,会导致每行出现填充数据。如:

  1. soc模式下,我们的Mat考虑执行效率,在创建Mat内存时每行数据会做64字节对齐,以适配硬件加速的需求(仅在soc模式下)。
  2. opencv的固有操作,如这个Mat是另一个Mat的子矩阵(即rect的选定区域),或者其他可能导致填充的操作。
    因此,按照opencv定义,通用处理方式就是在生成新的Mat的时候必须指定step,如下所示:
    cv::Mat image_mat = cv::imread(filename,IMREAD_COLOR,0);
    cv::Mat image_mat_temp(image_mat.rows,image_mat.cols,CV_8UC3,image_mat.data,image_mat.step[0]);
    cv::imwrite("sophgo1.jpg",image_mat_temp);
    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340