simd - 如何使用 NEON SIMD 合并 2 行的元素?

标签 simd intrinsics neon

我有一个

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

有没有单条 NEON SIMD 指令 哪个可以合并这两行?
或者如何使用内在函数使用尽可能少的步骤来实现这一点?

我想到了使用 压缩/解压缩 内在函数,但数据类型为 zip 功能 返回,即 float32x2x2_t , 不适合我,我需要一个 float32x4_t数据类型。
float32x2x2_t vzip_f32 (float32x2_t, float32x2_t)

最佳答案

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

你至少需要两个操作来进行转换..首先是一个向量转,它像这样排列你的参数:

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.

如果从内存加载数据,则可以跳过第一条 vtrn.32 指令,因为 NEON 可以在使用 vld2.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 代码可能会获得更好的性能。

关于simd - 如何使用 NEON SIMD 合并 2 行的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3343372/

相关文章:

c++ - 在 ARM NEON 中的数组边界上加载 vector

上交所/AVX : Choose from two __m256 float vectors based on per-element min and max absolute value

Android NDK ARM build设置以在大多数设备上运行?

c - 在 ARM Neon 汇编中使用 C 变量

arm - 用于在矩形和极坐标之间转换的 NEON 代码

c++ - 我的代码中的 “Peel/Remainder”循环无效

c# - 包装 System.Numerics.VectorS 的成本很高——为什么?

c# - 使用 C# Vector<T> SIMD 查找匹配元素的索引

performance - 英特尔内部指南 - 延迟和吞吐量

arm - 应使用哪个编译器将 C 代码移植到 ARM?