ios - 在 NEON float32x4_t 中总结 3 条车道

标签 ios arm simd neon intrinsics

我正在使用 ARM NEON 内在函数(llvm、iOS)对内部循环进行矢量化。我通常使用 float32x4_t。我的计算结束时需要对该向量中四个 float 中的三个求和。

此时我可以回到 C float 和 vst1q_f32 来获取四个值并将我需要的三个值相加。但我认为,如果有一种方法可以在一两条指令中直接使用向量来执行此操作,然后只获取一个 channel 结果,这可能会更有效,但我无法找出任何明确的路径来执行此操作。

我是 NEON 编程的新手,现有的“文档”非常糟糕。有任何想法吗?谢谢!

最佳答案

您应该能够使用 VFP 单元来完成此类任务。 NEON 和 VFP 共享相同的寄存器组,这意味着您无需为了充分利用一个单元而对寄存器进行混洗,它们还可以对相同的寄存器位有不同的看法。

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

您的 float32x4_t 是 128 位的,因此它必须位于一个四元 (Q) 寄存器中。如果您只使用 arm intrinsic,您将不知道您使用的是哪一个。如果它位于 4 以上,则存在问题,VFP 无法将其视为单一精度(对于好奇的读者:我保持简单,因为 VFP 版本之间存在差异,这是最低要求。).因此,最好将您的 float32x4_t 移动到固定寄存器,如 Q0。在此之后,您只需将 S0、S1、S2 等寄存器与 vadd.f32 相加,然后将结果移回 ARM 寄存器。

一些警告...VFP 和 NEON 理论上是不同的执行单元,共享相同的寄存器组和管道。我不确定这种方法是否比其他方法好,我不需要说,但你应该做基准测试。此外,这种方法并未使用 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;
}

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

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

关于ios - 在 NEON float32x4_t 中总结 3 条车道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13871113/

相关文章:

ios - 将 View (例如 Text())的不透明度设置为 0 或将背景设置为 Color.clear 会导致其不被绘制

c++ - 升级 gcc 编译器/其他修复以实现向后兼容

opencl - 如何向量化 3x3 2D 卷积?

c - 如何在 C 中的单个指令周期内添加 100 个整数元素的数组?

iPhone VS ipad开发过程(异同)

iphone - 委托(delegate)在 Controller A 中工作,但不在 Controller B 中工作

ios - Apple 处理器上的独家预留颗粒 (ERG)

linux - 适用于 ARM 的 Tizen IVI 3.0 移植

x86 - 我可以将 SIMD 内在函数用于在云上运行的软件吗?

ios - ARMv7 的 OSX 交叉编译库