在NEON float32x4_t中总计3个通道

Ben*_*tto 7 arm simd intrinsics neon ios

我正在使用ARM NEON内在函数(llvm,iOS)向量化内循环.我一般都在使用float32x4_ts.我的计算结束时需要对这个向量中的四个浮点数中的三个进行求和.

此时我可以回到C浮点数并vst1q_f32获得四个值并将我需要的三个加起来.但我认为如果有一种方法可以直接用一两条指令中的向量来实现它,那么只需抓住一条单一的通道结果,但我无法弄清楚这样做的任何明确路径.

我是NEON编程的新手,现有的"文档"非常可怕.有任何想法吗?谢谢!

aus*_*len 5

您应该能够将 VFP 单元用于此类任务。NEON 和 VFP 共享相同的寄存器组,这意味着您无需在寄存器周围进行混洗来利用一个单元,而且它们也可以对相同的寄存器位有不同的看法。

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204j/ch05s03s02.html

float32x4_t是 128 位,因此它必须位于 Quad (Q) 寄存器上。如果您仅使用 arm 内在函数,您将不知道您使用的是哪一个。问题是如果它高于 4,VFP 不能将其视为单精度(对于好奇的读者:我保持简单,因为 VFP 版本之间存在差异,这是最低要求。)。所以最好把你的移动float32x4_t到一个固定的寄存器,比如Q0. 在此之后,您可以对 S0、S1、S2 等寄存器进行求和,vadd.f32并将结果移回 ARM 寄存器。

一些警告... VFP 和 NEON 理论上是不同的执行单元,它们共享相同的寄存器组和管道。我不确定这种方法是否比其他方法更好,我不需要再说一次,你应该做基准测试。此外,这种方法并没有通过内在霓虹灯进行简化,因此您可能需要使用内联汇编来制作代码。

我做了一个简单的片段来看看它的样子,我想出了这个:

#include "arm_neon.h"

float32_t sum3() {           
        register float32x4_t v asm ("q0");
        float32_t ret;

        asm volatile(
        "vadd.f32       s0, s1\n"
        "vadd.f32       s0, s2\n"
        "vmov           %[ret], s0\n"
        : [ret] "=r" (ret)
        :
        :);

        return ret;
}
Run Code Online (Sandbox Code Playgroud)

objdump 它看起来像(用 gcc -O3 -mfpu=neon -mfloat-abi=softfp 编译)

00000000 <sum3>:
   0:   ee30 0a20   vadd.f32    s0, s0, s1
   4:   ee30 0a01   vadd.f32    s0, s0, s2
   8:   ee10 3a10   vmov    r0, s0
   c:   4770        bx  lr
   e:   bf00        nop
Run Code Online (Sandbox Code Playgroud)

如果你试一试,我真的很想听听你的印象!


rob*_*off 2

听起来您想使用(某些版本的)VLD1 将零加载到额外的通道中(除非您可以将其安排为零),然后使用两个 VPADDL 指令将四个通道两两相加,然后将两个通道相加合而为一。