非常慢的ffmpeg / sws_scale() - 仅在重负荷

时间:2018-06-01 13:07:37

标签: c++ windows visual-studio ffmpeg

我正在使用ffmpeg编写视频播放器(仅限Windows,Visual Studio 2015,64位编译)。 使用常见视频(最高4K @ 30FPS),效果非常好。但凭借我的最大目标 - 4K @ 60FPS,它失败了。解码仍然足够快,但是当谈到YUV / BGRA转换时,它的速度根本不够快,即使它是在16个线程中完成的(16/32核心机器上每帧一个线程)。

因此,作为第一个对策,我跳过了一些帧的转换,并以这种方式获得了~40的稳定帧速率。比较Concurrency Visualizer中的两个版本,我发现了一个奇怪的问题,我不知道原因。

这是frameskip版本的图片: enter image description here 你看到转换非常快(平均约为35毫秒) 因此,当使用多个线程时,它也应该足够快到60FPS,但它不是!

非frameskip版本的图像显示了原因: enter image description here 单帧的转换速度比以前慢了十倍(平均约为350毫秒)。现在,许多核心上的繁重工作量当然会导致每个核心的轻微减速,因为涡轮增压减少 - 比方说10%或20%。但绝不会出现~1000%的极端放缓。

有趣的细节是,非frameskip版本的堆栈跟踪显示了一些我不太了解的系统活动 - 从ntoskrnl.exe!KiPageFault+0x373开始。没有例外,其他错误消息等 - 它变得非常慢。

编辑:一位同事刚刚告诉我,这看起来像内存问题乍一看已分页内存 - 但我的内存利用率很低(低于1GB,超过20GB免费)

有人能告诉我是什么原因引起的吗?

1 个答案:

答案 0 :(得分:1)

这可能太旧了,无法使用,但仅作记录:

可能正在发生的事情是您在多个线程中一次又一次地分配4k帧。 Windows分配器确实不喜欢这种访问模式。

malloc本身不会显示在事件探查器中,因为只有在实际访问内存时,操作系统才会获取页面。它显示为ntoskrnl.exe!KiPageFault,并归因于该函数首先访问新内存。

解决方案包括:

  • 使用其他分配器(例如tbb_malloc,mimalloc等)
  • 使用您自己的每个线程或每个进程框架池。 ffmpeg在内部做类似的事情,也许您可​​以只使用that