为 ARM 交叉编译时未初始化特征向量 [英] Eigen vectors not initialized when cross-compiled for ARM

查看:44
本文介绍了为 ARM 交叉编译时未初始化特征向量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 arm-linux-gnueabihf-g++(来自 Linaro 的 gcc 4.8 版)的交叉编译程序上使用 Eigen3.目标平台是来自gumstix 的duovero,使用Poky 发行版- ARMv7.当我使用 Eigen 代码运行程序时,我在 Eigen 对象上得到了非常奇怪的值(请参阅本文末尾的输出示例).

I'm using Eigen3 on a cross compiled program using the arm-linux-gnueabihf-g++ (gcc version 4.8 from Linaro). The target platform is a duovero from gumstix using the Poky distribution - ARMv7. When I run the program with the Eigen code I get really strange values on the Eigen objects (see the output example at the end of this post).

我试图关闭矢量化,我已经使用了所有这些标志

I've tried to turn off vectorization, I've played with all these flags

-marm 
-mcpu=cortex-a7
-mfpu=neon 
-mfloat-abi=hard 

但总是得到相同的行为.如果我在 duovero 上编译相同的代码,它可以正常工作(向量已正确初始化),但在我交叉编译时就不行.我什至从不同的主机(windows7 和 ubuntu 14.04)交叉编译.

but always get the same behavior. If I compile the same code on the duovero it works ok (vectors are properly initialized) but not when I cross-compile. I've even cross-compiled from different hosts (windows7 and ubuntu 14.04).

知道为什么会这样吗?

这是我的简单程序(根据评论更新)

This is my simple program (updated from comments)

#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;
}

这是我得到的输出(更新)

This is the output I get (updated)

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 我收到这个错误

Edit When I add the flag: -mfloat-abi=soft I get this error

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.

update: I tried what Notlikethat suggested. Tested the libraries (ex. readelf -h /usr/lib/libstdc++.so.6.0.18) and found that the current built is definitively soft-float ABI.

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

When I link statically my the code works well (even if cross compiler is for hard float, this works because the hardware actually has an FPU even if the image is configured for soft fp). The next thing I did was to find a cross compiler that is able to do do softfp, and it also worked when I added the flag. I downloaded it from https://launchpad.net/linaro-toolchain-binaries/+milestone/2012.04.

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

I guess my next step is to compile a poky image for the duovero that can do hard float. Has anyone done this?

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

final update: I've actually just compiled the latest poky image from yocto (poky 1.7) for the duovero using these instructions https://github.com/gumstix/yocto-manifest

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

and realised that this build uses hard fp. Now my cross compiler (arm-linux-gnueabihf-g++) and the target have the same floating point configuration and my code with Eigen and everything else is working perfectly! Happy! :)

推荐答案

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

The problem would seem to be that you have a soft-float libstdc++ (and friends) on the device.

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

Consider an innocuous-looking function like std::ostream::operator<<(float) - when you cross-compile with the hard-float toolchain, you generate code which will pass the float to the function in an FPU register. The static linker knows enough to double-check that this matches the libraries it's linking against (the hard-float ones bundled with the cross-toolchain itself). Then you take that binary and run it on the device...

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

The dynamic linker, being less clever, is just going to make sure that whatever libstdc++ it finds provides the symbols the program is asking for. It finds one of a similar-enough version which fits that bill, so all seems good. Except now you've got the situation where your code is passing float arguments to library functions in FPU registers, but the library functions (being soft-float) are expecting their float arguments in general-purpose registers, so they find uninitialised junk.

最好的办法是完全避免针对一个库的链接,针对另一个库运行"的不匹配,对此有 3 种合理的选择,按严重程度的降序排列:

The best thing to do is to avoid the "link against one library, run against another" mismatch entirely, for which there are 3 reasonable options, in roughly decreasing order of severity:

  1. 交叉编译时静态链接.
  2. 将交叉工具链的硬浮动库放在设备文件系统的某个位置,让交叉编译的程序可以找到它们(可能求助于 LD_LIBRARY_PATH)——显然你不能简单地替换现有的库,否则你会得到相反的结果其余已安装程序的 ABI 不匹配.
  3. 将设备上的系统库复制到您的主机上,这样您就可以将交叉链接器指向它们而不是它的捆绑库,并使用 --mfloat-abi=soft 进行交叉编译.
  1. Link statically when you cross-compile.
  2. Put the cross-toolchain's hard-float libraries somewhere on the device's filesystem where you cross-compiled programs can find them (possibly resorting to LD_LIBRARY_PATH) - obviously you can't simply replace the existing libraries or you'd get the inverse ABI mismatch for the rest of your installed programs.
  3. Copy the system libraries off the device onto your host machine, so you can point the cross-linker at them instead of its bundled libraries, and cross-compile with --mfloat-abi=soft.

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

I'd normally suggest option 3 as the general case, however hard-float does have somewhat of a performance benefit so for floating-point-intensive code, so it may well be worth the bit of effort to get it to work.

请注意,虽然一些硬浮动(即arm-linux-gnueabihf-")跨工具链还包括通过 multilib 的软浮动库,其他(如我使用的 Linaro 库)要么不要,要么只为代表古代目标的选项的特定组合启用它们,这可能是您不想要的.如果您确实有一个合适的 multilib 工具链,那么@TurboJ 在评论中的建议是关于 - 使用 arm-linux-gnueabihf-gcc 作为链接命令( arm-linux-gnueabihf-ld) 和 --mfloat-abi=soft 指定会告诉它链接到它的库的软浮动版本如果它支持.

Note that whilst some hard-float (i.e. "arm-linux-gnueabihf-") cross-toolchains also include soft-float libraries via multilib, others (like the Linaro ones I use) either don't, or only enable them for specific combinations of options representing ancient targets, which you probably don't want. If you did have a suitable multilib toolchain, that's what @TurboJ's suggestion in the comments is about - using arm-linux-gnueabihf-gcc as the link command (not arm-linux-gnueabihf-ld) with --mfloat-abi=soft specified would tell it to link against the soft-float versions of its libraries if it supports that.

这篇关于为 ARM 交叉编译时未初始化特征向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆