4

私は

A = a1 a2 a3 a4
    b1 b2 b3 b4
    c1 c2 c3 c4
    d1 d2 d3 d4

私は私と2列を持っています、

float32x2_t a = a1 a2
float32x2_t b = b1 b2

これらからどうやって得ることができますか -

float32x4_t result = b1 a1 b2 a2

これらの 2 つの行をマージできる単一の NEON SIMD 命令はありますか? または、組み込み関数を使用して可能な限り最小限の手順でこれを達成するにはどうすればよいですか?

zip/unzip組み込み関数を使用することを考えましたが、 zip 関数が返すデータ型はfloat32x2x2_t、私には適していませんfloat32x4_t。データ型が必要です。

float32x2x2_t vzip_f32 (float32x2_t, float32x2_t)
4

1 に答える 1

5

これは難しいです。これを実行できる命令は1つではありません。最良の解決策は、データがメモリにあるか、すでにレジスタにあるかによって異なります。

変換を行うには、少なくとも2つの操作が必要です。最初に、次のように引数を並べ替えるベクトルターンを実行します。

a = a1 a2
b = b1 b2

vtrn.32  a, b

a = a1 b1 
b = a2 b2

次に、各操作の引数を交換する必要があります。各ベクトルをそれ自体で反転するか、2つのベクトルをクワッドベクトルとして扱い、長い反転を実行します。

temp = {a, b} 
temp = a1 b1 a2 b2

vrev64.32 temp, temp

temp = b1 a1 b2 a2    <-- this is what you want.

メモリからデータをロードする場合、NEONはvld2.32命令を使用してデータをロードしている間にこれを実行できるため、最初のvtrn.32命令をスキップできます。これはまさにそれを行う小さなアセンブラ関数です:

.globl asmtest

asmtest:
        vld2.32     {d0-d1}, [r0]   # load two vectors and transose
        vrev64.32   q0, q0          # reverse within d0 and d1
        vst1.32     {d0-d1}, [r0]   # store result
        mov pc, lr                  # return from subroutine..

ところで、ちょっとした注意:vtrn.32、vzip.32、vuzp.32の命令は同じです(ただし、32ビットエンティティを使用している場合のみ)

そして、NEON組み込み関数を使用しますか?まあ-単にあなたがねじ込まれていると言った。すでに知っているように、あるタイプから別のタイプに直接キャストしたり、クワッドベクトルとダブルベクトルを直接混合したりすることはできません。

これは私が組み込み関数を使用して思いついた最高のものです(読みやすさのためにvld2.32トリックを使用していません):

int main (int argc, char **args)
{
  const float32_t data[4] =
  {
    1, 2, 3, 4
  };

  float32_t     output[4];

  /* load test vectors */
  float32x2_t   a = vld1_f32 (data + 0);
  float32x2_t   b = vld1_f32 (data + 2);

  /* transpose and convert to float32x4_t */
  float32x2x2_t temp   = vzip_f32 (b,a);
  float32x4_t   result = vcombine_f32 (temp.val[0], temp.val[1]);

  /* store for printing */
  vst1q_f32 (output, result);

  /* print out the original and transposed result */
  printf ("%f %f %f %f\n", data[0],   data[1],   data[2],   data[3]);
  printf ("%f %f %f %f\n", output[0], output[1], output[2], output[3]);
}

GCCを使用している場合、これは機能しますが、GCCによって生成されたコードはひどく遅くなります。NEONの本質的なサポートはまだ非常に若いです。ここでは、単純なCコードを使用するとパフォーマンスが向上する可能性があります。

于 2010-08-08T06:24:24.727 に答える