Eigen库数据结构内存对齐问题

来源:互联网 发布:javascript表单提交 编辑:程序博客网 时间:2024/05/16 08:54

原文链接:http://blog.csdn.net/rs_huangzs/article/details/50574141


我这里讲的是在用到开源库Eigen中的数据结构时会出现这样的错误
error C2719: 't': formal parameter with __declspec(align('16')) won't be aligned
意思就是t: 具有 __declspec(align('16')) 的形参将不被对齐
还有一种错误的提示就是:
Assertion failed: (reinterpret_cast<size_t>(array) & 0xf) == 0 && "this assertion is explained here: http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****", file c:\eigen3.2.7\eigen\src\core\densestorage.h, line 86
导致上述两个错误的原因是因为Eigen库为了使用SSE加速,所以内存分配上使用了128位的指针。如果大家觉得我说的不够详细,也可以去Eigen网站里去看英文的解释。这里我只讲下面的三种情况,因为在我的代码中这三种情况都涉及到了,所以也专门看了网站上的解决方法

  • Structures having Eigen objects as members
  • STL Containers
  • Passing Eigen objects by value
    上面三种情况的意思就是Eigen库中的数据结构作为自定义的结构体或者类中的成员STL容器含有Eigen的数据结构Eigen数据结构作为函数的参数
    另外的一种情况我没有遇到过,所以也就不详细叙述了,本人也没有仔细的去看,如果我有时间看了,我会把解决方法也贴出来。
  • Compiler making a wrong assumption on stack alignment (for instance GCC on Windows)

Structures having Eigen objects as members

官方给的例子是如果你的代码是下面这个样子的,在你自定义的类中,成员中有Eigen的数据结构,

class Foo{  //...  Eigen::Vector2d v;  //...};//...Foo *foo = new Foo();

这个错误比较难发现,因为它在编译的时候是不会提示有错误的,只会在运行的时候提示出错,错误的提示就是Assertion failed: (reinterpret_cast<size_t>(array) & 0xf) == 0 && "this assertion is explained here: " "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****", file c:\eigen3.2.7\eigen\src\core\densestorage.h, line 86
这是因为你在使用这个类的时候用到了new方法,这个方法是开辟一个内存,但是呢在上面的代码中没有自定义构造函数,所以在new的时候会调用默认的构造函数,调用默认的构造函数的错误在于内存的位数不对齐,所以会导致程序运行的时候出错。 解决的方法就是在类中加入宏EIGEN_MAKE_ALIGNED_OPERATOR_NEW, 如下:

 class Foo{  ...  Eigen::Vector2d v;  ...public:  EIGEN_MAKE_ALIGNED_OPERATOR_NEW};


通过查找这个宏,我们可以找到这样一句代码#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign),大致意思就是指针对齐。
大家可以自己新建一个控制台程序来验证上述的解决方案是否对。很简单的代码,copy一下就可以了。本人已经试验了,可以完美解决上述的错误。

STL Containers

如果STL容器中的元素是Eigen库数据结构,例如这里定义一个vector容器,元素是Matrix4d ,如下所示:

vector<Eigen::Matrix4d>;

这个错误也是和上述一样的提示,编译不会出错,只有在运行的时候出错。解决的方法很简单,定义改成下面的方式:

vector<Eigen::Matrix4d,Eigen::aligned_allocator<Eigen::Matrix4d>>;

其实上述的这段代码才是标准的定义容器方法,只是我们一般情况下定义容器的元素都是C++中的类型,所以可以省略,这是因为在C++11标准中,aligned_allocator管理C++中的各种数据类型的内存方法是一样的,可以不需要着重写出来。但是在Eigen管理内存和C++11中的方法是不一样的,所以需要单独强调元素的内存分配和管理。

Passing Eigen objects by value

如果自定义的一个函数中的参数有Eigen数据类型,对于这个参数需要特别的注意,大多数情况下,我们学习的C++相关的书中,函数和参数的定义如下:

FramedTransformation( int id, Eigen::Matrix4d t );

这个错误会在你编译的时候提示你错误,错误的信息是error C2719: 't': formal parameter with __declspec(align('16')) won't be aligned
要解决这个错误也是很简单的,只有我们把参数t的类型稍加变化即可。如下:

FramedTransformation( int id, const Eigen::Matrix4d& t );
0 0