【问题标题】:Eigen vectors not initialized when cross-compiled for ARM为 ARM 交叉编译时未初始化特征向量
【发布时间】:2015-07-19 22:37:11
【问题描述】:

我在使用 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)交叉编译。

知道为什么会这样吗?

这是我的简单程序(从 cmets 更新)

#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。

当我静态链接时,我的代码运行良好(即使交叉编译器用于硬浮点,这是因为硬件实际上具有 FPU,即使图像配置为软 fp)。接下来我做的是找到一个能够做softfp的交叉编译器,当我添加标志时它也可以工作。我是从https://launchpad.net/linaro-toolchain-binaries/+milestone/2012.04 下载的。

我想我的下一步是为可以进行硬浮动的 duovero 编译一个 poky 图像。有人做过吗?

最终更新: 实际上,我刚刚使用这些说明为 duovero 编译了来自 yocto (poky 1.7) 的最新 poky 图像https://github.com/gumstix/yocto-manifest

并意识到此构建使用硬 fp。现在我的交叉编译器 (arm-linux-gnueabihf-g++) 和目标具有相同的浮点配置,我的 Eigen 代码和其他一切都运行良好!快乐的! :)

【问题讨论】:

  • 这肯定闻起来像一个浮动 ABI 问题(我什至不排除在库代码中出现一些狡猾的“在 x86 上工作正常”) - 在“玩过这些标志”中,你的意思是说你已经明确尝试过-mfloat-abi=soft?交叉编译器很可能配置有与本机不同的默认值,因此您不一定希望选项的 absence 意味着一致的行为。
  • 当我添加 -mfloat-abi=soft 我得到这个错误:ld.exe: 错误: testingEigen 使用 VFP 寄存器参数,main.obj 没有(我编辑了原始问题并添加了我从编译器得到的完整输出)。此时我的交叉编译器似乎只配置为硬浮点。 Eigen 是否需要软浮点才能工作?
  • -mfloat-abi=soft 添加到编译器标志之外的链接器标志。
  • 嗯,像cout &lt;&lt; 0.5f &lt;&lt; endl; 这样简单的事情还是一样吗?
  • @TurboJ,如果我只将 -mfloat-abi=soft 添加到链接器标志(而不是编译器标志),它可以编译,但如果我保留它作为编译器标志,我会遇到同样的问题提到了 VFP 寄存器参数。我开始认为问题在于交叉编译器仅适用于硬浮点。对于适用于 Windows 的带有 soft 或 softfp 的 ARM 交叉编译器有什么建议吗?

标签: gcc arm cross-compiling eigen eigen3


【解决方案1】:

问题似乎是您的设备上有一个软浮点 libstdc++(和朋友)。

考虑像std::ostream::operator&lt;&lt;(float) 这样看似无害的函数 - 当您使用硬浮点工具链进行交叉编译时,您生成的代码会将浮点数传递给 FPU 寄存器中的函数。静态链接器足够了解它是否与它所链接的库匹配(与交叉工具链本身捆绑在一起的硬浮动库)。然后你获取那个二进制文件并在设备上运行它......

动态链接器不太聪明,只是要确保它找到的任何 libstdc++ 都提供程序要求的符号。它找到了一个符合该要求的足够相似的版本,所以一切看起来都很好。除了现在您的代码将浮点参数传递给 FPU 寄存器中的库函数,但库函数(软浮点)期望它们在通用寄存器中的浮点参数,因此它们会发现未初始化的垃圾。

最好的办法是完全避免“链接一个库,运行另一个库”完全不匹配,对此有 3 个合理的选择,大致按严重程度递减顺序:

  1. 交叉编译时静态链接。
  2. 将交叉工具链的硬浮点库放在设备文件系统的某个位置,您可以在其中交叉编译的程序可以找到它们(可能使用 LD_LIBRARY_PATH) - 显然您不能简单地替换现有的库,否则您会得到相反的结果其他已安装程序的 ABI 不匹配。
  3. 将系统库从设备复制到您的主机上,这样您就可以将交叉链接器而不是捆绑的库指向它们,并使用 --mfloat-abi=soft 进行交叉编译。

我通常建议将选项 3 作为一般情况,但是硬浮点确实具有一定的性能优势,因此对于浮点密集型代码而言,因此值得付出一些努力来让它工作.

请注意,虽然一些硬浮点(即“arm-linux-gnueabihf-”)交叉工具链还包括通过 multilib 的软浮点库,但其他(如我使用的 Linaro)要么不启用它们,要么仅启用它们以用于代表古代目标的特定选项组合,这可能是您不想要的。如果您确实有一个合适的 multilib 工具链,那就是 @TurboJ 在 cmets 中的建议 - 使用 arm-linux-gnueabihf-gcc 作为链接命令(不是 arm-linux-gnueabihf-ld)和 @如果支持,指定的 987654325@ 会告诉它链接到其库的软浮点版本。

【讨论】:

    猜你喜欢
    • 2021-08-11
    • 1970-01-01
    • 2019-05-21
    • 2011-07-24
    • 2014-12-05
    • 2012-08-04
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    相关资源
    最近更新 更多