GLSL:计算时间取决于数据值吗?

时间:2013-09-18 09:16:27

标签: opengl glsl fft gpgpu data-transfer

最近,我一直致力于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 ms
  • Shader:32.7854 ms
  • 传输GPU-CPU:29.8564 ms

但如果我这样做(现在,我将返回计算的真正价值):

    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;}
    }

我必须等待 ~500ms 才能得到结果(记录如下)。

  • 创建fbo:24.7944 ms
  • Shader:456.967 ms
  • 传输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/

如果您需要更多详情,请询问。

1 个答案:

答案 0 :(得分:3)

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

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

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

时间当然可以根据价值观而改变。例如,我相信矩阵与零的乘法可以明显更快(虽然我自己没有测试过)。我也看到了非常大的数字,特别是无效数字的性能发生了巨大的变化(在这些情况下,我做了一些愚蠢的事情,允许这些值首先存在)。