我使用arm-linux-gnueabihf-g ++(来自Linaro的gcc版本4.8)在交叉编译的程序中使用Eigen3。目标平台是来自gumstix的duovero使用Poky发行版 - ARMv7。当我使用Eigen代码运行程序时,我在Eigen对象上得到了非常奇怪的值(请参阅本文末尾的输出示例)。
我试图关闭矢量化,我玩过所有这些旗帜
-marm
-mcpu=cortex-a7
-mfpu=neon
-mfloat-abi=hard
但总是得到相同的行为。如果我在duovero上编译相同的代码,它可以正常工作(向量已正确初始化),但在交叉编译时则不行。我甚至从不同的主机(windows7和ubuntu 14.04)交叉编译。
知道为什么会这样吗?
这是我的简单程序(从评论中更新)
#include <iostream>
using namespace std;
#include <stdio.h>
#include <Eigen/Eigen>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
cout << "Hello World!" << endl;
int j =3;
cout << j << endl << endl; // ok
float k =4.2;
cout << k << endl << endl; // not ok
printf("%f\n\n", k ); // ok
Vector3d test1;
test1 << 1.2, 2.3, 3.4;
cout << test1 << endl << endl; // not ok
printf("%f\n\n", test1(0) ); // ok
Vector3d test2(1,2,3);
cout << test2 << endl; // not ok
cout << test2(1) << endl << endl; // not ok
printf("%f\n\n", test2(0) ); // ok
cout << 0.5f << endl; // not ok
printf("%f\n\n", 0.5f ); // ok
return 0;
}
这是我得到的输出(更新)
Hello World!
3
0
4.200000
-1.24694e-06
-1.24695e-06
-1.24695e-06
1.200000
-1.24692e-06
-1.24692e-06
-1.24693e-06
3.8852e+68
1.000000
0
0.500000
编辑 当我添加标志:-mfloat-abi = soft时出现此错误
arm-linux-gnueabihf-g++ -c -mfloat-abi=soft -g -Wall -W -fPIE -IC:\tmp\testingEigen -I. -IC:\COSMOS\source\thirdparty\arm\eigen3 -IC:\Qt\5.4\mingw491_32\mkspecs\linux-arm-gnueabihf-g++ -o main.obj C:\tmp\testingEigen\main.cpp
arm-linux-gnueabihf-g++ -o testingEigen main.obj
c:/program files (x86)/linaro/gcc-linaro-arm-linux-gnueabihf-4.8-2014.01/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld.exe: error: testingEigen uses VFP register arguments, main.obj does not
makefile:79: recipe for target 'testingEigen' failed
c:/program files (x86)/linaro/gcc-linaro-arm-linux-gnueabihf-4.8-2014.01/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld.exe: failed to merge target specific data of file main.obj
更新 我尝试了Notlikethat建议的内容。测试了这些库(例如readelf -h /usr/lib/libstdc++.so.6.0.18),发现当前构建的是明确的软浮动ABI。
当我静态链接时,我的代码运行良好(即使交叉编译器用于硬浮动,这也可行,因为即使图像配置为软fp,硬件实际上也有FPU)。我接下来要做的是找到一个能够做softfp的交叉编译器,当我添加标志时它也能工作。我是从https://launchpad.net/linaro-toolchain-binaries/+milestone/2012.04下载的。
我想我的下一步是为duovero编制一个可以做硬浮动的poky图像。有没有人这样做过?
最终更新 我实际上只是使用这些说明从yocto(poky 1.7)为duovero编制了最新的poky图像https://github.com/gumstix/yocto-manifest
并意识到这个版本使用了硬fp。现在我的交叉编译器(arm-linux-gnueabihf-g ++)和目标具有相同的浮点配置和我的代码与Eigen和其他一切工作完美!快乐! :)
答案 0 :(得分:2)
问题似乎是你在设备上有一个软浮动的libstdc ++(和朋友)。
考虑一个看似无害的函数,如std::ostream::operator<<(float)
- 当您使用hard-float工具链进行交叉编译时,会生成将浮动函数传递给FPU寄存器中的函数的代码。静态链接器知道足以仔细检查它是否匹配它链接的库(与交叉工具链本身捆绑的硬浮点数)。然后你拿这个二进制文件并在设备上运行它......
动态链接器不那么聪明,只是要确保它找到的libstdc ++提供程序要求的符号。它找到了一个类似的版本,适合该法案,所以一切似乎都很好。除了现在你已经得到了你的代码将浮点参数传递给FPU寄存器中的库函数的情况,但是库函数(软浮点函数)期望它们在通用寄存器中的浮点数,所以它们找到未初始化的垃圾
最好的办法是避免与一个库相关联,与另一个库运行。完全不匹配,有3种合理的选择,严重程度大致递减:
--mfloat-abi=soft
进行交叉编译。我通常会建议将选项3作为一般情况,但是对于浮点密集型代码而言,硬浮动确实有一些性能优势,因此获得它可能值得花一些时间。工作。
请注意,虽然一些硬浮动(即&#34; arm-linux-gnueabi hf - &#34;)交叉工具链还包括通过multilib的软浮动库,其他(如#34; arm-linux-gnueabi hf - &#34;)我使用的Linaro(或者不是),或者只是为了代表古代目标的特定选项组合启用它们,这些选项可能是您不想要的。如果确实有一个合适的multilib工具链,那么@TurboJ在评论中的建议是什么 - 使用arm-linux-gnueabihf-gcc
作为链接命令( not指定arm-linux-gnueabihf-ld
的 --mfloat-abi=soft
)会告诉它链接其库的soft-float版本(如果它支持的话)。