Cortex A9 NEON与VFP使用混淆

cel*_*vek 20 c c++ floating-point arm neon

我正在尝试为Cortex A9 ARM处理器(更具体的OMAP4)构建一个库,我对于哪些\何时在浮点运算和SIMD中使用NEON vs VFP有点困惑.需要注意的是,我知道2个硬件协处理器单元之间的区别(这也在SO上有所描述),我对它们的正确使用有一些误解.

与此相关我使用以下编译标志:

GCC
-O3 -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp
-O3 -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp
ARMCC
--cpu=Cortex-A9 --apcs=/softfp
--cpu=Cortex-A9 --fpu=VFPv3 --apcs=/softfp
Run Code Online (Sandbox Code Playgroud)

我已经阅读了ARM文档,很多wiki(比如这个),论坛和博客文章,每个人似乎都同意使用NEON比使用VFP或至少混合NEON更好(例如使用instrinsics来实现一些算法在SIMD中)和VFP并不是一个好主意; 如果这适用于整个application\library的上下文或仅适用于代码中的特定位置(函数),我还不是100%确定.

所以我在我的应用程序中使用neon作为FPU,因为我也想使用内在函数.结果我遇到了一些麻烦,我对如何在Cortex A9上最好地使用这些功能(NEON vs VFP)的困惑只是进一步深化而不是清理.我有一些代码为我的应用程序进行基准测试,并使用一些自定义的计时器类,其中计算基于双精度浮点.使用NEON作为FPU会产生完全不合适的结果(尝试打印这些值会导致打印主要是inf和NaN;相同的代码在为x86构建时没有任何障碍).所以我改变了我的计算以使用单精度浮点,据记载,NEON不处理双精度浮点.我的基准测试仍然没有给出正确的结果(最糟糕的是现在它在x86上不再起作用了;我认为这是因为精度的损失,但我不确定).所以我几乎完全迷失了:一方面我想使用NEON用于SIMD功能并使用它,因为FPU没有提供正确的结果,另一方面将它与VFP混合似乎不是一个好主意.在这方面的任何建议将不胜感激!!

我在上面提到的wiki的文章中找到了在NEON上下文中浮点优化应该做些什么的总结:

"

  • 仅使用单精度浮点
  • 当您发现瓶颈FP功能时,请使用NEON内在函数/ ASM.你可以比编译器做得更好.
  • 最小化条件分支
  • 启用RunFast模式

对于softfp:

  • 内联浮点代码(除非它非常大)
  • 通过指针而不是值传递FP参数,并在函数调用之间执行整数工作.

"

我不能用于浮动ABI,因为我无法链接到我可用的库.大多数的推荐对我来说都是有意义的(除了"快速模式",我不明白应该做什么以及此时我能做得比编译器更好的事实)但我不断得到不一致的结果和我现在不确定.

任何人都可以了解如何正确使用浮点和NEON用于Cortex A9/A8以及我应该使用哪些编译标志?

uni*_*urf 8

我认为这个问题应该分成几个,添加一些代码示例并详细说明目标平台和使用的工具链版本.

但要掩盖一部分困惑:"使用NEON作为FPU"的建议听起来像是一种误解.NEON是SIMD引擎,VFP是FPU.您可以在最多4个并行的单精度值上使用NEON进行单精度浮点运算,这样(如果可能)有利于提高性能.

-mfpu=neon可以看作是速记-mfpu=neon-vfpv3.

有关更多信息,请参阅http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html.


jww*_*jww 8

...论坛和博客文章,每个人似乎都同意使用NEON比使用VFP或至少混合NEON(例如使用instrinsics在SIMD中实现一些算法)更好,VFP不是一个好主意

我不确定这是否正确.据ARM 介绍NEON开发文章| NEON注册:

NEON寄存器库由32个64位寄存器组成.如果同时实现了高级SIMD和VFPv3,则它们共享该寄存器组.在这种情况下,VFPv3以VFPv3-D32形式实现,支持32个双精度浮点寄存器.此集成简化了实现上下文切换支持,因为保存和恢复VFP上下文的相同例程也可以保存和恢复NEON上下文.

NEON单元可以查看相同的寄存器组:

  • 16个128位四字寄存器,Q0-Q15
  • 32个64位双字寄存器,D0-D31.

NEON D0-D31寄存器与VFPv3 D0-D31寄存器相同,每个Q0-Q15寄存器映射到一对D寄存器.图1.3显示了共享NEON和VFP寄存器组的不同视图.所有这些视图都可以随时访问.软件不必在它们之间明确切换,因为使用的指令决定了适当的视图.

寄存器不竞争; 相反,它们作为注册银行的观点共存.没有办法去除NEON和FPU装备.


与此相关我使用以下编译标志:

-O3 -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp
-O3 -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp
Run Code Online (Sandbox Code Playgroud)

这就是我的所作所为; 你的旅费可能会改变.它源于从平台和编译器收集的混合信息.

gnueabihf告诉我平台使用硬浮动,这可以加快程序调用.如果有疑问,请使用,softfp因为它与硬浮子兼容.

BeagleBone Black:

$ gcc -v 2>&1 | grep Target          
Target: arm-linux-gnueabihf

$ cat /proc/cpuinfo
model name  : ARMv7 Processor rev 2 (v7l)
Features    : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 
...
Run Code Online (Sandbox Code Playgroud)

所以BeagleBone使用:

-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard
Run Code Online (Sandbox Code Playgroud)

CubieTruck v5:

$ gcc -v 2>&1 | grep Target 
Target: arm-linux-gnueabihf

$ cat /proc/cpuinfo
Processor   : ARMv7 Processor rev 5 (v7l)
Features    : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 
Run Code Online (Sandbox Code Playgroud)

所以CubieTruck使用:

-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard
Run Code Online (Sandbox Code Playgroud)

Banana Pi Pro:

$ gcc -v 2>&1 | grep Target 
Target: arm-linux-gnueabihf

$ cat /proc/cpuinfo
Processor   : ARMv7 Processor rev 4 (v7l)
Features    : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
Run Code Online (Sandbox Code Playgroud)

所以Banana Pi使用:

-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard
Run Code Online (Sandbox Code Playgroud)

树莓派3:

RPI3的独特之处在于其ARMv8,但它运行的是32位操作系统.这意味着它实际上是32位ARM Aarch32.对于32位ARM与Aarch32有一点点,但这将显示Aarch32标志

此外,RPI3使用Broadcom A53 SoC,它具有NEON和可选的CRC32指令,但缺少可选的加密扩展.

$ gcc -v 2>&1 | grep Target 
Target: arm-linux-gnueabihf

$ cat /proc/cpuinfo 
model name  : ARMv7 Processor rev 4 (v7l)
Features    : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
...
Run Code Online (Sandbox Code Playgroud)

所以Raspberry Pi可以使用:

-march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard
Run Code Online (Sandbox Code Playgroud)

或者它可以使用(我不知道该用什么-mtune):

-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard 
Run Code Online (Sandbox Code Playgroud)

ODROID C2:

ODROID C2使用Amlogic A53 SoC,但它使用64位操作系统.ODROID C2,它具有NEON和可选的CRC32指令,但缺少可选的加密扩展(类似于RPI3的配置).

$ gcc -v 2>&1 | grep Target 
Target: aarch64-linux-gnu

$ cat /proc/cpuinfo 
Features    : fp asimd evtstrm crc32
Run Code Online (Sandbox Code Playgroud)

所以ODROID使用:

-march=armv8-a+crc -mtune=cortex-a53
Run Code Online (Sandbox Code Playgroud)

在上面的配方中,我通过检查数据表了解了ARM处理器(如Cortex A9或A53).根据Unix和Linux Stack Exchange上的这个答案,它解密输出/proc/cpuinfo:

CPU部件:部件号.0xd03表示Cortex-A53处理器.

所以我们可以从数据库中查找值.我不知道它是否存在或它位于何处.