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.8564ms

しかし、私がそうするなら (今、私はコンピューティングの真の価値を返します):

    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 に答える