我们正在开发工作站 Core i7 和 AMD FirePro 8000。对于视频解码(8K,7680x4320 视频帧 ~ 66MB hapq 编解码器),我们尝试使用以下明显的循环:
- 从流中获取帧
- 地图缓冲区
- 多线程解码帧切片到映射缓冲区
- 取消映射缓冲区
- texsubimage 从绑定的 PBO 转换为纹理
但是步骤 3. 将多线程切片解码到映射缓冲区 非常慢 - 至少需要大约 40 毫秒才能完成
当我们把它分成两个步骤时
3a。将多线程的帧切片解码到分配的内存中
3b。memcpy 从 malloced 内存到映射缓冲区
两个步骤都需要 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-cache 问题。