ARM Cortex-A 处理器和 GCC 命令行

本文转自:

http://community.arm.com/community/arm-cc-cn/blog/2013/10/24/arm-cortex-a-%E5%A4%84%E7%90%86%E5%99%A8%E5%92%8C-gcc-%E5%91%BD%E4%BB%A4%E8%A1%8C

感谢原作者!



ARM Cortex-A 处理器和 GCC 命令行

Posted by Song Bin 宋斌 in 中文社区 on Oct 24, 2013 10:06:00 AM

原文: ARM Cortex-A Processors and GCC Command Lines

投稿人:richardearnshaw2013 4 15

 

面向 ARM 处理器的 GNU 编译器集合 (GCC) 命令行选项最初是在多年前设计的,当时可用处理器和变体的列表与现今相比要短很多。随着 ARM 架构的演进,从 GCC 中获取最佳代码所需的选项也已改变,但也做了各种尝试来确保选项的现有集合不会改变其本意。编译器的设计意味着充分利用 ARM CortexTM-A 处理器 所需的选项现在已非常复杂。本文阐述 GCC 命令行选项的三大方面:CPU、浮点和 SIMD(单指令多数据)加速。

 

应当针对我的 CPU 使用什么选项?

首先,我们来看看用于告知编译器您所使用的 CPU 的主要选项;然后,我们来阐述一些可在特殊情形中使用的更为高级的选项。

 

在您编译文件时,编译器都需要知道您要用于运行结果代码的 CPU 类型。实现这一目的的主要选项是 -mcpu=<cpu-name> 选项。正如您可能预想到的,cpu-name 替换为您拥有的 CPU 类型的具体名称,但使用小写。例如,对于 Cortex-A9,该选项为 -mcpu=cortex-a9GCC 目前支持到 Cortex-A15(含)为止的所有 Cortex-A,即:

Cortex-A5 -mcpu=cortex-a5

 

Cortex-A7 -mcpu=cortex-a7

 

Cortex-A8 -mcpu=cortex-a8

 

Cortex-A9 -mcpu=cortex-a9

 

Cortex-A15 -mcpu=cortex-a15

 

如果您的 GCC 版本无法识别上述之一或许其版本太旧您应当考虑升级。如果不指定要使用的 CPUGCC 将使用其内置的默认值。这会因编译器原先构建的方式而不同,可能意味着生成的代码在您所拥有的 CPU 上执行时速度非常缓慢(或者无法执行)。

 

添加浮点和 SIMD

目前市面上的所有 ARM Cortex-A 处理器都配有浮点单元,大多数也拥有实施 ARM 高级 SIMD 处理器扩展(通常称为 NEONTM)的 SIMD 单元。然而,准确的可用指令集根据您所拥有的 CPU 而不同,GCC 需要单独的选项来进行控制;它不会尝试从 -mcpu 选项进行处理。对浮点和 SIMD 指令的选择是通过 –mfpu 选项控制的,下表中列出了各种 CPU 的建议选择:

blogentry-103749-004812900 1365712953_thumb.png

处理器

仅浮点

浮点 + SIMD

Cortex-A5

 

 

Cortex-A7

 

 

Cortex-A8

 

 

Cortex-A9

 

 

Cortex-A15

 

 

 

VFPv3 VFPv4 实施从 32 个双精度寄存器开始;但是,在没有 NEON 时,上部 16 个寄存器变为可选;这是通过选项名称的 d16 部分控制的。该名称的 fp16 部分指定是否存在半精度(16 位)浮点加载、存储和转换指令;这是对 VFPv3 的扩展,但在所有 VFPv4 实施中都可用。

 

由于历史原因,如果被明确告知这么做是安全的,GCC 将仅使用浮点和 NEON 指令。对此进行控制的选项有些令人混淆,选项的一部分也可更改编译器所遵守的 ABI。选项 -mfloat-abi 有三个可能的选项:

-mfloat-abi=soft -- 忽略所有 FPU NEON 指令,仅使用核心寄存器集合,并通过库调用模拟所有浮点运算。

 

-mfloat-abi=softfp -- 使用与 -float-abi=soft 相同的调用约定,但会根据需要使用浮点和 NEON 指令。此选项二进制兼容 -mfloat-abi=soft,可用于改善必须遵守软浮点环境的代码的性能,但需要是已知相关硬件指令也可用的环境。

 

-mfloat-abi=hard -- 根据需要使用浮点和 NEON 指令,也会更改 ABI 调用约定来生成效率更高的函数调用;现在可以在扩展寄存器中于函数之间传递浮点和矢量类型,不仅节约大量复制操作,也意味着需要在堆栈上传递参数的调用变少。

 

应当使用上述选项中的哪一个在很大程度上取决于您的目标系统,也可能默认选项就是正确的选项。例如,Ubuntu 12.04 (Precise) 现在默认使用 -mfloat-abi=hard

 

矢量化浮点运算

NEON 架构包含同时对整数和浮点数据类型进行运算的指令,GCC 现在拥有强大的自动矢量化优化,可发现何时适合使用可改善性能的矢量引擎。不过,让许多用户讶异的是,即使他们可能希望要这么做,编译器也无法矢量化其代码。

 

首先要记住的是,自动矢量化器只有在 -O3 时默认启用。有可以在其他时候将它打开的选项,您可以在 GCC 手册中找到相关内容。

 

然而,即使启用了矢量化器,浮点代码也常常不能矢量化。其原因为,尽管 NEON 中的浮点运算使用 IEEE 单精度格式来容纳值,为了最小化 NEON 单元中所需的功率并且最大化吞吐量,只有在输入和结果在正常运算范围内(即值不是非正常值或 NaN)时,矢量引擎才会完全按照标准进行编译。GCC 默认配置为生成严格遵守 IEEE 浮点算法规范的代码,前文所述的限制意味着默认使用 SIMD 指令是不适当的。

 

幸运的是,GCC 确实提供了多个命令行选项,可用于准确控制需要的 IEEE 标准遵守级别。虽然细节已超过本文的讨论范畴,在大多数情形中,使用 -ffast-math 选项来放宽规则并启用矢量化是完全安全的。

 

此外,也可在 GCC 4.6 或更高版本中使用 -Ofast 选项来实现基本相同的效果。它会打开 -O3 以及多种其他优化,通常可以安全地用于从您的代码中获得最佳的性能。

 

要记住的另一点是,NEON 仅支持单精度数据的矢量运算。除非您编写的代码用于处理这一格式,否则可能会发现矢量化并不可行。您也应当了解,浮点常量(字面值)最终会强制编译器以双精度执行计算。在 C C++ 中,请编写 '1.0F' 而非 '1.0' 确保编译器了解您的意思。

 

最后,如果对于找出矢量化器为何不按您预期运作的原因依然存有疑问,而且您也准备好亲自动手探究,GCC 对于其所做的行为提供了非常丰富的信息。-fdump-tree-vect -ftree-vectorizer-verbose=<level> 选项控制所生成的信息量,级别是 1 9 范围内的数字。虽然生成的大多数信息只有编译器开发人员才会感兴趣,但您不时也会在输出结果中找到提示,了解您的代码不能按预期矢量化的原因。

 

总而言之

看来,选项有许多,我的日常运算中应当使用哪个呢?幸运的是,一旦确定了目标环境,大多数的选项不会时常更改。以下是一些示例:

 

具有 NEON Cortex-A15 处理器,以及操作使用浮点数据类型的数据阵列的一些浮点代码。该运行环境可以支持在浮点寄存器中传递参数:

arm-gcc -O3 -mcpu=cortex-a15 -mfpu=neon-vfpv4 -mfloat-abi=hard \

-ffast-math -o myprog.exe myprog.c

 

不带 NEON Cortex-A7 处理器,处理浮点代码。该运行环境仅支持在整数寄存器中传递参数,但可以使用浮点硬件

arm-gcc -O3 -mcpu=cortex-a7 -mfpu=vfpv4-d16 -mfloat-abi=softfp \

-o myprog2.exe myprog2.c

 

最后,Cortex-A9 处理器在浮点/NEON 寄存器集合全都无法使用的环境中运作(例如,因为它在中断处理程序的中间,并且浮点上下文保留用于用户状态)。

arm-gcc -O3 -mcpu=cortex-a9 -mfloat-abi=soft -c -o myfile.o myfile.c

 

相关 ARM 博客:

 

 

 

Richard Earnshaw ARM 首席工程师,也是 ARM GNU 编译器工具团队的技术总管和软件架构师。除了其他工作外,他在编译器工作方面拥有将近 20 年的经验,也是 GCC 全球评论员的一员。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值