OpenGL PBO 映射缓冲区:多线程解包慢,memcpy 快

问题描述 投票:0回答:2

我们正在开发工作站 Core i7 和 AMD FirePro 8000。对于视频解码(8K、7680x4320 视频帧 ~ 66MB hapq 编解码器),我们尝试使用以下明显的循环:

  1. 从流中获取帧
  2. 地图缓冲区
  3. 将多线程帧切片解码到映射缓冲区中
  4. 取消映射缓冲区
  5. 将 texsubimage 从绑定的 PBO 转换为纹理

但是步骤 3.将多线程切片解码到映射缓冲区中 速度慢得可怕 - 至少需要 40 毫秒才能完成

当我们将其分为两步时

3a。将多线程帧切片解码到分配的内存中

3b。 memcpy 从 malloc 内存到映射缓冲区

这两个步骤都需要 8+9 ~ 17ms 才能完成。现在我们有了一个可以接受的解决方案,但是额外的复制步骤很痛苦。

为什么多线程解包到映射内存中的速度如此之慢?我们如何避免额外的复制步骤?

编辑1;

这就是缓冲区的生成、定义和映射方式:

glGenBuffers(1, &hdf.m_pbo_id);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, hdf.m_pbo_id);
glBufferData(GL_PIXEL_UNPACK_BUFFER, m_compsize, nullptr, GL_STREAM_DRAW);
hdf.mapped_buffer = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);

编辑2:

有人提出了如何测量时间的问题。仅测量非 gl 代码。伪代码是这样的,

情况1(非常慢,t2-t1 ~ 40ms):

gl_map();
t1 = elapse_time();
unpack_multithreaded_multiple_snappy_slices_into_mapped_buffer();
t2 = elapse_time();
gl_unmap();

情况2(中慢,t3-t2~9ms,t2-t1~8ms):

gl_map();
malloc_sys_buffer();
t1 = elapse_time();
unpack_multithreaded_multiple_snappy_slices_into_sys_buffer();
t2 = elapse_time();
memcpy_sys_buffer_into_mapped_buffer();
t3 = elapse_time();
gl_unmap();

在测量的代码块内不涉及 OpenGL 代码。也许这是一个直写/CPU 缓存问题。

multithreading opengl directx amd-gpu
2个回答
1
投票

解包到映射内存中的速度很慢,因为该内存是写组合的。对于此类内存的每次写入,完整的缓存行都会通过总线传输到 GPU。与此内存交互的最佳方法是以尽可能大的块写入数据。为了避免额外的复制步骤,您可能需要修改解码器以写入大的连续内存块。尝试一下写入的线程数也很好。 这里有一个很好的概述https://fgiesen.wordpress.com/2013/01/29/write-combining-is-not-your-friend/


0
投票

我也在做同样的事情。我遇到了同样的问题,写入映射缓冲区非常慢。我尝试了不同的 pbo 创建设置,发现以下设置可以实现相当好的性能:

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_id);
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, pbo_size, 0, GL_MAP_WRITE_BIT | GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
pbo_ptr = (unsigned char*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, new_pbo.m_size, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
© www.soinside.com 2019 - 2024. All rights reserved.