树莓派ARM浮点ABI兼容性

4

我目前在我的Ubuntu机器上进行一些适用于树莓派的交叉编译测试。我现在的理解是,树莓派支持硬件浮点运算,并且默认的Raspbian操作系统映像是使用硬件浮点运算(armhf)构建的。正确吗?

如果我使用“arm-linux-gnueabi”工具链(不指定任何ARM标志)构建我的应用程序,则我的应用程序将使用软件浮点ABI。正确吗?

在这种情况下,为了能够正确链接,我所有的依赖项也必须使用相同的ABI。正确吗?

如果我的应用程序使用软件浮点ABI,则我的应用程序肯定已经链接到一个软件浮点ABI共享标准库。当我在我的树莓派上运行我的应用程序时,一切都按预期工作。如果Raspbian使用硬件浮点ABI(而我猜测共享标准库也是如此),那么这是怎么做到的呢?

FYI:我的默认arm-linux-gnueabi已配置为:

--with-float=soft
--with-arch=armv5

我正在这样编译我的应用程序:

arm-linux-gnueabi-g++ test.cpp -o test

我的程序确实包含浮点数计算:

double test = (123.456 + 789.123) * 1.23;
printf("%f\n", test); // prints: 1122.472170
printf("%f\n", std::floor(test)); // prints: 1122.000000

你的程序中使用浮点数吗? - syam
也许你的应用程序根本不使用浮点数? - auselen
我已经尝试了“打破它”。请参见上面的编辑。 - pqvst
1
尝试一些其他的东西,比如sqrt或power,而不是printf。 - auselen
树莓派中的ARM11芯片应该是armv6,而不是armv5。 - old_timer
1个回答

7
你的所有观点都是正确的,我只想补充一下关于Raspbian的armhf的一些细节。
Debian的armhfarm-linux-gnueabihf)针对ARMv7t硬件浮点运算。由于Raspbian基于Debian,你会期望它也是一样的,但是Raspbian的armhf针对ARMv6硬件浮点运算(这也是Raspbian存在的原因:在Debian的armel(ARMv4t软件浮点运算)和armhf架构之间找到一个折中方案来正确利用树莓派的CPU)。
因此,对于Raspbian来说,讲述armhf有点危险,特别是因为很多人会使用Debian(或者像Ubuntu这样的衍生版本)作为主机系统,所以容易混淆两者。如果你问我,Raspbian的人犯了一个错误,他们应该使用不同的架构名称,例如arm6hf

当我在我的树莓派上运行应用程序时,一切都如预期一样。但是,如果Raspbian使用了硬件浮点ABI(我猜测共享的标准库也是这样),那么这是怎么回事呢?

据我所知,arm-linux-gnueabiarm-linux-gnueabihf之间唯一的区别就是涉及浮点运算的调用约定(前者使用整数寄存器传递,后者使用浮点寄存器传递)。
如果你的测试程序从未使用浮点ABI(我的意思是你不会通过CPU/FPU寄存器将浮点数传递给外部库 - 但是你可以完全使用软件浮点进行浮点计算 - 并在实际“使用”第三方库之前将结果转换为int),那么你永远不会遇到ABI差异,一切都能正常工作。
关于你提供的使用浮点数的例子,我认为它们属于我刚才描述的类别:你从未使用过硬件浮点ABI。
  • 很有可能std::floor被内联了(最好的方法是查看汇编转储)。
  • printf使用可变参数,因此实际上使用的是传统的C调用约定,即参数通过堆栈传递,而不是通过CPU/FPU寄存器传递。

无论如何,你应该避免使用当前的arm-linux-gnueabi工具链,并使用专门为Raspbian设计的工具链。只需在网络上搜索“Raspberry Pi cross-compiler”即可。这样你就不会被困扰了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接