我目前正在尝试使用OpenGL ES 2.0在移动设备(带有OMAP 3630 / PowerVR SGX 530的诺基亚N9)上进行一些GPGPU图像处理。基本上我的应用程序的管道将彩色图像上传到视频内存,将其转换为灰度,计算整体图像并在几个片段着色器的帮助下提取一些特征。
输出正确,但程序的运行时有点令人困惑。当我将相同的图像通过我的管道3次以上时,时间是这样的(在第3次定时保持不变之后):
RGB-to-gray conversion: 7.415769 ms
integral image computation: 818.450928 ms
feature extraction: 285.308838 ms
RGB-to-gray conversion: 1471.252441 ms
integral image computation: 825.012207 ms
feature extraction: 1.586914 ms
RGB-to-gray conversion: 326.080353 ms
integral image computation: 2260.498047 ms
feature extraction: 2.746582 ms
如果我排除特征提取,则积分图像计算的时间变为合理的:
RGB-to-gray conversion: 7.354737 ms
integral image computation: 814.392090 ms
RGB-to-gray conversion: 318.084717 ms
integral image computation: 812.133789 ms
RGB-to-gray conversion: 318.145752 ms
integral image computation: 812.103271 ms
如果我另外从管道中排除了积分图像计算,则会发生这种情况(也是合理的):
RGB-to-gray conversion: 7.751465 ms
RGB-to-gray conversion: 9.216308 ms
RGB-to-gray conversion: 8.514404 ms
我期望的时间更像是:
RGB-to-gray conversion: ~8 ms
integral image computation: ~800 ms
feature extraction: ~250 ms
基本上,时间与我的期望有两点不同:
我怀疑着色器切换是1)性能下降的原因。但这真的有这么大的影响吗?特别是当考虑到特征提取步骤包含具有不同片段着色器和FBO开关的多次传递时,但仍然如预期的那样快。
特别奇怪的是性能下降2.)在积分图像计算期间,因为它是一个多遍操作,只使用一个着色器和乒乓渲染目标。如果我为每次传球测量glDraw*()
的性能,则在所有传球中只发生一次,并且总是在同一传球中(尽管在这传球中没有发生任何特殊情况)。
我还怀疑内存限制是原因,因为我使用了很多纹理/ FBO来输出数据,但总而言之,我占用了大约6 MB的视频内存,实际上并没有那么多。 / p>
我已经尝试glDrawElements()
,glDrawArrays()
和glDrawArrays()
与VBO每次都有相同的结果。
所有时间都被捕获:
glFinish();
timer.start();
render();
glFinish();
timer.stop();
如果我忽略了glFinish()
的来电,时间是相同的。
有没有人有想法,我可能做错了什么?我对OpenGL并不太懂,所以也许有人可以指出我应该注意的方向或事情。我知道如果没有任何代码示例,这很难回答,这就是为什么我要求相当一般的建议。如果你需要更多关于我正在做的事情的信息,我会很高兴提供一些代码或伪代码。我只是不想太夸大这个问题...
我想我找到了导致性能下降的原因:它似乎是两个着色器之间的某种等待时间,其中OpenGL管道等待先前的片段着色器完成,然后将输出交给下一个片段着色器。我使用rgb2gray转换着色器进行了一些实验,可以分离出两种情况:
1。)使用rgb2gray着色器的第二次渲染取决于第一次渲染的输出:
|inImg| -> (rgb2gray) -> |outImg1| -> (rgb2gray) -> |outImg2|
2。)第二次渲染不依赖:
|inImg| -> (rgb2gray) -> |outImg1|
|inImg| -> (rgb2gray) -> |outImg2|
显然,变量2。)很可能比1.)更快,但是,我不明白为什么管道在第一次执行时以合理的运行时间完成,但是有那些奇怪的延迟之后。
另外我认为最后一个流水线步骤的运行时间测量总是不准确的,所以我假设~280 ms是一个更准确的特征提取步骤测量(不是〜3 ms)。
答案 0 :(得分:2)
我认为问题可能出在测量方法上。定时单个GL命令甚至渲染是非常困难的,因为驱动程序将试图通过并行运行多个渲染的不同部分来保持GPU管道的所有阶段繁忙。由于这个原因,驱动程序可能忽略了glFinish并且只在必要时才等待硬件完成(例如渲染目标上的glReadPixels)。
如果驱动程序只是将它们添加到队列的末尾,那么单个渲染可能会很快完成,但如果需要等待队列中的空间并且必须等待较早的渲染完成,那么单个渲染可能会很慢。
更好的方法是运行大量的帧(例如1000)并测量所有帧的总时间。