【发布时间】:2013-09-18 09:16:26
【问题描述】:
最近,我一直在研究 fft 算法。我使用 glsl 来更快地计算它。 该算法工作正常,非常好,但是时间测量的结果很奇怪:
如果我这样做:
uniform sampler2D resultRe;
uniform sampler2D resultIm;
uniform int n;
void main(void)
{
float v = 2.0*n;
float x = gl_TexCoord[0].x - 0.5;
float y = gl_TexCoord[0].y - 0.5;
float re = texture2D(resultRe, vec2(x/n,y/n));
/* fft */
if(x<n*0.5){
gl_FragColor.r = re;//w1+w5;
gl_FragColor.g = re;}//w2+w6;}
if(x>n*0.5-1.0){
gl_FragColor.r = re;//w1-w5;
gl_FragColor.g = re;}//w2-w6;} //range of re <0,255>,
//but if I multiply re by
//-10000.0, the time of computing
//is almost the same.
}
计算 fft(按列)的时间约为 83ms(日志如下)。
- 创建 fbo:20.6251 毫秒
- 着色器:32.7854 毫秒
- 传输 GPU-CPU:29.8564 毫秒
但如果我这样做(现在,我返回计算的真正价值):
uniform sampler2D resultRe;
uniform sampler2D resultIm;
uniform int n;
void main(void)
{
float v = 2.0*n;
float x = gl_TexCoord[0].x - 0.5;
float y = gl_TexCoord[0].y - 0.5;
float iy = y/n; //for glsl purpose
float ix = x/n;
float w1=0.0, w2=0.0, w3=0.0, w4=0.0;
float rad = 0.0;
float g = x;
if(g>n*0.5-1.0) x-=n*0.5;
float rad2 = -dPI*g/n;
/* fft here */
float w5 = (w3*cos(rad2)-w4*sin(rad2));
float w6 = (w3*sin(rad2)+w4*cos(rad2));
if(x<n*0.5){
gl_FragColor.r = w1+w5;
gl_FragColor.g = w2+w6;}
if(x>n*0.5-1.0){
gl_FragColor.r = w1-w5;
gl_FragColor.g = w2-w6;}
}
我必须等待 ~500 毫秒 才能得到结果(日志如下)。
- 创建 fbo:24.7944 毫秒
- 着色器:456.967 毫秒
- 传输 GPU-CPU:28.6295ms
问题是:为什么?执行时间不取决于值,是吗?我想不出任何主意。
为了加快数据传输速度,我试过使用这个:http://www.mathematik.uni-dortmund.de/~goeddeke/gpgpu/tutorial3.html#prep,但失败了。
时间测量:http://www.lighthouse3d.com/tutorials/opengl-short-tutorials/opengl-timer-query/
如果您需要更多详细信息,请询问。
【问题讨论】:
-
第二个例子中 w1-w6 的定义在哪里?它看起来怎么样?
-
从目前我们可以看到,第二个示例根本无法编译。
-
@user:你真的对第二个着色器执行得慢得多感到惊讶吗?您在其中添加三角函数,一般来说,通过添加更多算术来应对 ALU 的挑战,而在您的第一个示例中,您所做的最昂贵的事情可能是纹理查找。
-
好的...让我换个方式。这两个片段都是同一个着色器的片段。但起初,我返回了计算结果,然后我通过返回“re”值替换了我共享的一部分(返回值)。现在清楚了吗?在这两种情况下,都会计算 cos ans sinus
-
它不仅取决于数据值,想象一下从随机或远距离纹理坐标进行采样——你完全搞乱了 GPU 进行纹理缓存的能力——而且它还取决于数据 type我>。您在代码中使用了一堆标量,没有向量;你陷入了 CPU 心态。
标签: opengl glsl fft gpgpu data-transfer