最近,我一直致力于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 (记录如下)。
但如果我这样做(现在,我将返回计算的真正价值):
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 才能得到结果(记录如下)。
问题是:为什么?执行的时间不取决于价值,是吗?我无法想出任何想法。
为了加快数据传输速度,我尝试使用它:http://www.mathematik.uni-dortmund.de/~goeddeke/gpgpu/tutorial3.html#prep但我失败了。
时间测量:http://www.lighthouse3d.com/tutorials/opengl-short-tutorials/opengl-timer-query/
如果您需要更多详情,请询问。
答案 0 :(得分:3)
GLSL编译器(至少是Nvidia / ATI)使用非常积极的优化。 如果输出中未使用某个值,则只会将其删除。这甚至可以在着色器阶段发生。例如,如果变化值对片段着色器输出没有贡献,则在顶点着色器中忽略该值的计算。我发现基准测试着色器可能非常棘手,因为GLSL做了很多我意想不到的事情。
要强制计算一个值,请使用它做一些简单的事情。例如,将其添加到颜色中(甚至按比例缩小,因此它实际上不会对颜色产生太大影响)。
查看着色器二进制文件有时也很有用:glGetProgramBinary(如果您的GLSL编译器/驱动程序包含与我类似的类似人类可读组件的代码)
时间当然可以根据价值观而改变。例如,我相信矩阵与零的乘法可以明显更快(虽然我自己没有测试过)。我也看到了非常大的数字,特别是无效数字的性能发生了巨大的变化(在这些情况下,我做了一些愚蠢的事情,允许这些值首先存在)。