1

以下はIIRコードです。NEON コードを効率的に記述できるように、コードをベクトル化する必要があります。

ベクトル化の例 ベクトル化されてい ないコード

for(i=0;i<100;i++)
a[i] =a[i]*b[i];     //only one independent multiplication cannot take
                     //advantage of multiple multiplication units

ベクトル化されたコード

for(i=0;i<25;i++)
{
a[i*4] =a[i*4]*b[i*4];                //four  independent multiplications can use
a[(i+1)*4] =a[(i+1)*4]*b[(i+1)*4];    // multiple multiplication units to perform the 
a[(i+2)*4] =a[(i+2)*4]*b[(i+2)*4];    //operation in parallel
a[(i+3)*4] =a[(i+3)*4]*b[(i+3)*4];
}

ハードウェアのベクトル機能を使用してコードを効率的に実装するために、以下の for ループをベクトル化するのを手伝ってください (私のハードウェアは 4 つの乗算を同時に実行できます)。

 main()
    {
        for(j=0;j<NUMBQUAD;j++)
    {
        for(i=2;i<SAMPLES+2 ;i++)
        {
            w[i] = x[i-2] + a1[j]* w[i-1] + a2[j]*w[i-2];
            y[i-2] = w[i] + b1[j]* w[i-1] + b2[j]*w[i-2];

        }
        w[0]=0;
        w[1] =0;
    }
    }
4

1 に答える 1

1

方程式を修正 (または検証) すると、方程式の各ラウンドに 4 つの独立した乗算があることに気付くはずです。タスクは、入力ベクトル x[...]、y[...]、w[...] を何らかのレジスターに並べ替えるための適切で最小の命令数を見つけることになります。

   q0 = | w[i-1] | w[i-2] | w[i-1] | w[i-2]|
   q1 = | a1[j]  | a2[j]  | b1[j]  | b2[j] |   // vld1.32 {d0,d1}, [r1]!
   q2 =   q0 .* q1

for ループを逆にすることで、波面の並列処理の潜在的にはるかに効果的な方法を実現できます。

   x0 = *x++;

   w0 =  x0 + a*w1 + b*w2;  // pipeline warming stage
   y0 =  w0 + c*w1 + d*w2;  // 

   [REPEAT THIS]
     // W2 = W1; W1 = W0;
     W0 = y0 + A*W1 + B*W2;
     Y0 = W0 + C*W1 + D*W2;
     // w2 = w1; w1 = w0;

     x0 = *x++;
     *output++= Y0;

     w0 = x0 + a*w1 + b*w2;
     y0 = w0 + c*w1 + d*w2;
   [REPEAT ENDS]

   W0 = y0 + A*W1 + B*W2;   // pipeline cooling stage
   Y0 = W0 + C*W1 + D*W2;
   *output++= Y0;

x0->w0->y0->W0->Y0 の間にはまだ依存関係がありますが、小文字と大文字の式の間に完全な双方向並列処理の機会があります。w2=w1; w1=w0;また、ループをアンロールして手動でレジスタの名前を変更することで、値のシフトをなくすこともできます。

于 2013-04-05T09:34:58.000 に答える