【问题标题】:GLSL: does the time of computing depend on data value?GLSL:计算时间是否取决于数据值?
【发布时间】: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


【解决方案1】:

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

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

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

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

【讨论】:

  • 有趣。我该如何使用它?我应该在代码的哪里做?
  • 这是我找到的关于它的页面:nicolaslelong.fr/2011/08/about-using-glarbgetprogrambinary.html 至少对于 Nvidia,我目前不需要提示 GL_PROGRAM_BINARY_RETRIEVABLE_HINT,但它在规格中,所以不要指望便携性不。它吐出一堆二进制数据,然后是我只能假设是类汇编代码的明文表示,它似乎做了 GLSL 代码所做的事情。带上一粒盐,但它以前对我有帮助。
  • 谢谢,我也找到了这个页面。也许我不明白,因为它不起作用: GLuint loadAndCompileShaders(const GLchar *d[],GLint Lenghts[],const GLchar *d1[],GLint Lenghts1[]) {/*这里是创建和编译着色器*/ p=glCreateProgram(); glAttachShader(p,v); glAttachShader(p,f);闪烁长度; glProgramParameteri(p,GL_PROGRAM_BINARY_RETRIEVABLE_HINT,GL_TRUE); glGetProgramiv(p,GL_PROGRAM_BINARY_LENGTH,&length); GLubyte *buffer = 新 GLubyte[长度]; glGetProgramBinary(p,length,0,0,buffer); glProgramBinary(p,0,buffer,length); glLink程序(p); glUseProgram(p);返回 p;}
  • glProgramBinary 用于将预编译的着色器上传回opengl。对于某些具有大量着色器的应用程序,在第一次执行时编译着色器然后保存到磁盘以供将来使用可能非常有用。在这种情况下,您只想将二进制文件写入文件。在 glLinkProgram 之前给出提示,然后在 glLinkProgram 之后调用 glGetProgramBinary 并将其写入文件。
  • +1 建议检查编译输出。但是,它不需要吐出基于文本的汇编语言。它可以是纯字节码;遗憾的是,OpenGL 规范提供了一种检索二进制着色器和选择格式的机制,但仅此而已。我希望看到一个标准化选项,要求实现显式输出基于文本的反汇编(用于调试/低级性能分析)或字节码(用于编译着色器缓存)。就此而言,如果您可以使用它直接加载汇编语言着色器并绕过 GLSL,那将是天堂!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
  • 2012-04-19
  • 2017-09-15
  • 1970-01-01
  • 2021-06-27
  • 2014-02-04
相关资源
最近更新 更多