我正在使用 OpenGL 对图像进行调整,所以我需要这种工作流程:
- 上传图像数据到显卡
- 变换图像
- 将结果下载回主存
每一步都会停止,直到上一步完成。这可以。我需要尽快完成所有这些步骤。与其他操作多路复用对我来说不是一个改进;我需要尽快完成这张图片。
现在,2 真的很快,3 也不错,很可能是因为结果是原始图像的缩略图——小得多。
1是我的瓶颈。我测量了在 1.2 秒内上传 20MB 的图像数据。这让我达到了 16MB/s 的速度。在 Internet 的其他地方,我读到有人期望 5.5GB/s,但对 2.5GB/s 感到失望。
我是glTexImage2D
直接使用还是通过PBO来做都没关系。我都试过了,没有测量出任何区别。这是有道理的,因为我没有与任何东西进行多路复用。对于我的管道,无论如何我都无法在不立即停止的情况下使用 PBO。
我能想到的剩下的解释是:我的系统就是这么慢。我的显卡是 NVIDIA GPU GeForce GTX 285 (GT200),通过 16x PCI-Express 连接。我测得的 16MB/s 是不是和这个速度一样快,还是我忽略了什么?是否存在可以让我测量最大数据速率的实用程序(通常用于 Ubuntu/Linux)?
得出系统这么慢的结论让我感到不舒服。毕竟,我的网络接口速度非常快(1Gb/s ~ 125MB/s),并且只有 cat-5e 电缆可以实现这一点。
更多细节:glTexImage2D
案例非常简单:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rawData);
仅对这条线计时即可测量 ~1200ms。
如前所述,我还将其翻译为使用 PBO:
GLuint pbo = 0;
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER, data_size, pixels, GL_STREAM_DRAW);
glTexImage2D(target, level, internalformat, width, height, border, format, type, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
glDeleteBuffers(1, &pbo);
我也尝试过内存映射:
glBufferData(GL_PIXEL_UNPACK_BUFFER, data_size, 0, GL_STREAM_DRAW);
GLubyte* ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
std::copy(pixels, pixels+data_size, ptr);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
任何解决方案之间的时间没有明显差异。
上传纹理数据时,我应该期望什么样的数据速率?
我的设置 16MB/s 合理吗?(我觉得“不”。如果是,请告诉我!)
是否有一个工具可以用来验证这是我的系统的速度,从而证明我的代码是正确的,或者肯定将责任归咎于我的代码?