代码之家  ›  专栏  ›  技术社区  ›  HaggarTheHorrible

如何使用NEON SIMD合并两行的元素?

  •  4
  • HaggarTheHorrible  · 技术社区  · 16 年前

    我有一个

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

    我有两排,

    float32x2_t a = a1 a2
    float32x2_t b = b1 b2
    

    从这些我怎么能得到一个-

    float32x4_t result = b1 a1 b2 a2
    

    有吗 哪一行可以合并这两行? 或者我如何使用尽可能少的步骤来实现这一点?

    我想用 压缩/解压缩 但数据类型 zip函数 返回,这是 float32x2x2_t float32x4_t 数据类型。

    float32x2x2_t vzip_f32 (float32x2_t, float32x2_t)
    
    1 回复  |  直到 16 年前
        1
  •  5
  •   Nils Pipenbrinck    16 年前

    这很难。。没有一条指令可以做到这一点,最好的解决方案取决于数据是在内存中还是已经在寄存器中。

    你至少需要两个操作来进行转换。。首先是一个向量转向,它将你的论点排列成这样:

    a = a1 a2
    b = b1 b2
    
    vtrn.32  a, b
    
    a = a1 b1 
    b = a2 b2
    

    然后必须交换每个操作的参数。或者把每个向量自己倒过来,或者把两个向量当作一个四元向量,做一个长倒过来。

    temp = {a, b} 
    temp = a1 b1 a2 b2
    
    vrev64.32 temp, temp
    
    temp = b1 a1 b2 a2    <-- this is what you want.
    

    .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位实体时)

    这是我提出的使用内部函数的最好方法(它没有使用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生成的代码将是可怕的和缓慢的。我还很年轻。使用直接的C代码,您可能会获得更好的性能。。

    推荐文章