0

最近一直在研究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(按列)的时间约为83 毫秒(日志如下)。

  • 创建 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/

如果您需要更多详细信息,请询问。

4

1 回答 1

3

GLSL 编译器(至少是 Nvidia/ATI)使用了非常激进的优化。如果输出中没有使用一个值,它就会被删除。这甚至可能发生在着色器阶段。例如,如果变量值对片段着色器输出没有贡献,则在顶点着色器中忽略该值的计算。我发现基准着色器可能非常棘手,因为 GLSL 做了很多我觉得意想不到的事情。

要强制计算一个值,对它做一些简单的事情。例如将它添加到颜色中(甚至缩小了很多,因此它实际上不会对颜色产生太大影响)。

查看着色器二进制文件有时也会有所帮助:glGetProgramBinary如果您的 GLSL 编译器/驱动程序包含与我的类似的人类可读的类似汇编的代码

时间当然可以根据值而改变。例如,我相信矩阵乘以零可以明显更快(尽管我自己没有测试过)。我还看到非常大的数字,尤其是无效数字的性能发生了巨大变化(在这些情况下,我做了一些愚蠢的事情,一开始就允许这些值存在)。

于 2013-09-18T09:54:00.860 回答