rockchip-linux / mpp

Media Process Platform (MPP) module
593 stars 171 forks source link

有关mpp 拷贝解码后的数据 速度很慢解决方法? #80

Open ghost opened 5 years ago

ghost commented 5 years ago

我之前看到了有这个issue,我看您回复“要用的话,估计要在内核里加上解码输出 buffer 的自动 invalid 处理”,请问可否告知具体加入的方法?

HermanChen commented 5 years ago

目前的mpp不支持这种操作,需要基于特定版本的 sdk 专门开发。

ghost commented 5 years ago

目前的mpp不支持这种操作,需要基于特定版本的 sdk 专门开发。

有其他办法提高mpp解码出来的yuv数据拷贝到RAM的方法吗?

ghost commented 5 years ago

目前的mpp不支持这种操作,需要基于特定版本的 sdk 专门开发。

因为我们要对yuv数据进行人脸识别,所以都是CPU要直接访问内存的,所以我希望能有个办法把yuv数据更快的拷贝到内存中,我在3368上测试如果不拷贝,解码1080p 25fps CPU占用只有3%,如果要拷贝,单线程基本上吃满,而且只有10fps,所以希望有办法能快速拷贝帧

HermanChen commented 5 years ago

解码出来的数据本身就在 DDR 里,只是 mpp 使用的 ion / drm 内存默认是 no-cahce 的,访问时较慢 如果不修改为 cache 的话,只能提频了

HermanChen commented 5 years ago

如果要拷贝搬移部分数据的话,可以使用 RGA

HermanChen commented 5 years ago

人脸识别不会使用大张的全图,可以使用 RGA 做缩小拷贝,然后在小图里处理

ghost commented 5 years ago

解码出来的数据本身就在 DDR 里,只是 mpp 使用的 ion / drm 内存默认是 no-cahce 的,访问时较慢 如果不修改为 cache 的话,只能提频了

改cache会很复杂吗?可否点拨下我自己改?

ghost commented 5 years ago

人脸识别不会使用大张的全图,可以使用 RGA 做缩小拷贝,然后在小图里处理

我们方案是使用1080p全图的,所以需要拷贝整个yuv数据

HermanChen commented 5 years ago

开 cache 本身不复杂,但是开了 cache 之后,所有 cpu 的访问都需要加同步接口,很多平台没有提供这样的接口给上层,而 mpp 需要大量的 cpu / 硬件同步操作,这样使用中就会有问题,所以实现上都使用 non-cache 模式。

ghost commented 5 years ago

开 cache 本身不复杂,但是开了 cache 之后,所有 cpu 的访问都需要加同步接口,很多平台没有提供这样的接口给上层,而 mpp 需要大量的 cpu / 硬件同步操作,这样使用中就会有问题,所以实现上都使用 non-cache 模式。

我看到mpp里面有个配置mpp_buffer_group_get_internal(&frm_grp, MPP_BUFFER_TYPE_DRM);这个函数,如果设置成NORMAL会不会就不使用DRM了?

HermanChen commented 5 years ago

不行,NORMAL是一个debug用的路径,硬件解码需要 DRM / ION 这种类型,cache flag 是在 allocator_drm 里配置的

ghost commented 5 years ago

所有 cpu 的访问都需要加同步接口

我看到上一个问题有人说是outer_inv_range,dmac_inv_range,这个是您所说的同步接口吗?

HermanChen commented 5 years ago

这些是在老的3.10内核上ion的接口,drm 没有对应接口

ghost commented 5 years ago

这些是在老的3.10内核上ion的接口,drm 没有对应接口

如果我想改造,在新的内核是没办法的?

ghost commented 5 years ago

这些是在老的3.10内核上ion的接口,drm 没有对应接口

用memcpy_fromfs这个会比单纯memcpy更快吗

HermanChen commented 5 years ago

4.4内核目前没什么简单的办法,要有的话,需要在vpu驱动中找到输出buffer,对输出地址进行 invalidate,然后上层开 cache 去读取,可能会快一些

alandingbc commented 5 years ago

你好。最近开始研究mpp,follow这个issue之后,有一个问题也想请教一下。 如果mpp alloc的内存是drm 且 un-cached,是否意味着,只能调用rga处理,或直接塞到video vop plane进行显示,才不会有内存访问的性能损失? 其他任何软件以cpu访问该段内存都会因为un-cached导致不必要的损失,有实际的测试损耗数据嘛? 如果用rga,即 rga src 为 drm,rga dest 为normal,可以避免这个问题嘛? 看上去un-cached会导致一般的软件库没法处理解码后的数据。

ghost commented 5 years ago

其他任何软件以cpu访问该段内存都会因为un-cached导致不必要的损失,有实际的测试损耗数据嘛? 如果用rga,即 rga src 为 drm,rga dest 为normal,可以避免这个问题嘛? 看上去un-cached会导致一般的软件库没法处理解码后的数据。

如果只是显示,理论上性能损失很小,问题是我要做人脸识别,必须把数据拷出来,3368我这里测试60~70ms一帧1080p

“如果用rga,即 rga src 为 drm,rga dest 为normal,可以避免这个问题嘛?” 你可以试试,估计应该差不多

alandingbc commented 5 years ago

其他任何软件以cpu访问该段内存都会因为un-cached导致不必要的损失,有实际的测试损耗数据嘛? 如果用rga,即 rga src 为 drm,rga dest 为normal,可以避免这个问题嘛? 看上去un-cached会导致一般的软件库没法处理解码后的数据。

如果只是显示,理论上性能损失很小,问题是我要做人脸识别,必须把数据拷出来,3368我这里测试60~70ms一帧1080p

“如果用rga,即 rga src 为 drm,rga dest 为normal,可以避免这个问题嘛?” 你可以试试,估计应该差不多

我看了rga源码,rga也是利用dma做memory block transfer,但是rga自己的驱动会调用dma_flush_range来flush & invalid cache。主要问题是,rga好像也是要求mem必须是drm的。虽然支持normal mem,也应该只是debug testing用的。

具体能不能支持,我也没测试过。不过感觉可以利用rga驱动的机制来做,先把解码数据拷贝到cacheable内存,在cacheable内存中操作更靠谱。在vpu驱动中invalid decodec或encode buffer之后,后续如果还有其他处理,不清楚这样的操作会不会引起其他数据同步的bug。

@HermanChen 不知道这样的想法是否能成立,暂时还未测试,能否指教一下?

HermanChen commented 5 years ago

没问题,可以的,使用 rga 完成到 normal 的拷贝,思路正确~ 可以这样来,解码输出图像buffer直接给 rga 做输入,rga 读 ddr 里的数据没有 cache 的问题,然后输出到 normal 的 buffer,然后 invalid normal buffer,这样效率最高。 invalid 这些只针对 cpu cache 与 ddr 的一致,对硬件处理本身没有影响。

alandingbc commented 5 years ago

没问题,可以的,使用 rga 完成到 normal 的拷贝,思路正确~ 可以这样来,解码输出图像buffer直接给 rga 做输入,rga 读 ddr 里的数据没有 cache 的问题,然后输出到 normal 的 buffer,然后 invalid normal buffer,这样效率最高。 invalid 这些只针对 cpu cache 与 ddr 的一致,对硬件处理本身没有影响。

你好。我看了rga2的demo代码和文档,也看了驱动部分。 还是有一个问题。demo中直接alloc drm buffer,将读取的数据放置到src drm buffer,之后调用rga拷贝,最后将dest和src进行内存数据check。这中间没有执行invalid cache行为。如果内存是non-cache的,那么最后cpu将内存数据进行对比check的行为应该出错才对,但是多次测试都是正常的。 感觉虽然dest申请的是drm buffer,但是cacheable的,不知道我这样的表述是否正确? 如果可以直接操作dest的 drm buffer,感觉也不需要特意malloc一段normal buffer,再进行 invalid nornal buffer了。

HermanChen commented 5 years ago

cache 出错的前提是 cache 被 cpu 写入,是 dirty 状态,同时没有没有与 ddr 里的数据进行同步,导致的不一致的态,或者是数据读出到 cache 之后,ddr 数据被硬件写入这种的不一致状态。 如果这个 buffer 本身没有被 cpu 访问过,这时去读取数据的都是正常的。

HermanChen commented 5 years ago

如果是 non-cache 的,每次读取都会去 ddr 读取,而不是从 cache 读取,这样是永远不会出错的。

alandingbc commented 5 years ago

okay,了解了。多谢~!

HermanChen commented 5 years ago

客气,如果能解决问题的话,麻烦请关闭问题:)

alandingbc commented 5 years ago

此问题不是我open的…… -_-|

ghost commented 5 years ago

mo中直接alloc drm buffer,将读取的数据放置到src drm buffer,之后调用rga拷贝,最后将dest和src进行内存数据check。这中间没有执行invalid cache行为。如果内存是non-cache的,那么最后cpu将内存数据进行对比check的行为应该出错才对,但是多次测试都是正常的。 感觉虽然dest申请的是drm buffer,但是cacheable的,不知道我这样的表述是否正确? 如果可以直接操作dest的 drm buffer,感觉也不需要特意malloc一段normal buffer,再进行 invalid

你所说的demo是rga_test.cpp吗?

alandingbc commented 5 years ago

rockchip github中有开源库

liyuming1978 commented 5 years ago

rga.cpp 里面
request->mmu_info.mmu_en = 1; request->mmu_info.mmu_flag = 1; request->mmu_info.mmu_flag = ((2 & 0x3) << 4) | 1; request->mmu_info.mmu_flag |= (1 << 31) | (1 << 10) | (1 << 8); mmu这么配置的 , 我传入normal的内存不行, 返回rga出错, -3

一般来说, 应该是rga还是在uncache的内存操作, 然后返回以后, 再把内存cache一下, memcpy就快了 可是我不知道该怎么搞 @HermanChen

liyuming1978 commented 5 years ago

我把request->mmu_info.mmu_flag |= (1 << 31) | (1 << 8); 改成这样, 然后dst 改成normal, rga不返回错误了, 但是卡死在那了.. 吐血

liyuming1978 commented 5 years ago

有个疑问,我看mpp buffer getptr 里面已经对内存进行了mmap ,为啥用这个mmap的内存拷贝效率这么低

HermanChen commented 5 years ago

mpp 里分的 buffer 默认是 non-cache 的,访问效率不高

lawaarch commented 1 year ago

ee那就想整个解码接口还不行