std :: vector的对齐问题 [英] Alignment issues with std::vector

查看:97
本文介绍了std :: vector的对齐问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我终于遇到了这里描述的烦人的问题: https://eigen.tuxfamily.org/dox/group__TopicStlContainers.html

I finally ran into the annoying issue described here: https://eigen.tuxfamily.org/dox/group__TopicStlContainers.html

我有一个包含几个本征固定大小矩阵的结构,并且我想将我的结构的几个实例存储在std :: vector中.因此很明显,这些问题仅发生在固定大小的可矢量化特征类型和以此类特征对象为成员的结构中."适用.但是,仅描述了如何使用直接收集本征对象的向量而不是包含本征实例的结构来解决该问题.

I have a structure containing several Eigen fixed-size matrices, and i want to store several instances of my structure in a std::vector. So obviously 'These issues arise only with fixed-size vectorizable Eigen types and structures having such Eigen objects as member.' applies. However, it is only described how to solve the issue with vectors directly collecting Eigen Objects, not with structures containing Eigen instances.

目前我的问题是这样的:

Currently my problem looks like this:

struct MyStruct{
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW //Don't know if this applies here
    Eigen::Matrix<double, 4, 4> A;
    // several more instances and stuff here
    MyStruct ( ...)  // constructor taking several arguments, but only running an initilization list for some members

    // no destructor defined / implemented !

    // no methods!
}

//
MyStruct instanceStruct( .. constructing .. );
instanceStruct.A = someAssigment() ; 
// this type of 'instancing' before i push it into the vector is necessary ...

std::vector<MyStruct> myVector;
myVector.push_back( std::move( instanceStruct ) ); // gdb tells me that here we run into a SIGSEGV

是什么原因引起的问题?谢谢!

What causes the problem? Thank you!

推荐答案

从C ++ 17开始

需要标准容器使用的默认分配器来遵守对齐方式,任何存储持续时间(*)的变量也是如此.因此,在这种情况下,您的代码应该开箱即用,因为Eigen确实在需要的地方指定对齐方式.

From C++17 on

The default allocator used by standard containers is required to respect alignment, and so are variables of any storage duration (*). Therefore, your code should work out-of-the-box in this case, because Eigen do specify alignment where needed.

(*)虽然有:

  • 实现可能仍然会抛出bad_alloc或拒绝在请求不支持的对齐方式时编译定义.但是,据我所知,它不会静默地失败,也不会导致未定义的行为.

  • an implementation may still throw bad_alloc or refuse to compile definitions where an unsupported alignment is requested. But, as far as I know, it cannot fail silently, nor result in undefined behavior.

用户定义的分配器允许静默忽略过度对齐类型.此外,请注意,C ++ 17之前的库可能会在内部进行假设,从而绕过上述保证.通常,对于任何分配类型的设施(可能在内部),都应始终检查是否有过度对齐的类型支持.

user defined allocators are allowed to silently ignore over-aligned types. Moreover, beware that pre-C++17 libraries may make assumptions internally, circumventing the aforementioned guarantees. In general, you should always check for over-aligned type support for any facility allocating types (possibly internally).

您唯一需要担心的是通过新分配器或默认分配器获得的动态存储持续时间变量(请参见

The only(*) thing you should worry about are variables of dynamic storage duration obtained either via new or the default allocator (see P0035r4 for more details).

现在,Eigen通过提供EIGEN_MAKE_ALIGNED_OPERATOR_NEW和特征值:: aligned_allocator:

Now, Eigen fixes both by providing EIGEN_MAKE_ALIGNED_OPERATOR_NEW and Eigen::aligned_allocator:

struct MyStruct{
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW // this will make new MyStruct to work
//...

// this will make vector (or any other allocator-aware container) to work
std::vector<MyStruct,Eigen::aligned_allocator<MyStruct> >

请注意,与官方文档所说的相反,您可以在C ++ 11中使用任何对齐的分配器,因此无需#include< Eigen/StdVector> (必须包括它)如果是在C ++ 11之前的模式下进行编译,或者您的编译器不完全支持c ++ 11对齐语义).

note that, contrary to what the official doc says, you can use any aligned allocator in C++11, so there's no need to #include<Eigen/StdVector> (you must include it if compiling in pre-C++11 mode though, or if your compiler does not fully support c++11 alignment semantics).

或者,您可以禁用向量化(请参阅Eigen宏文档以了解操作方法)或仅通过new分配向量化矩阵:

Alternatively, you can disable vectorization (see Eigen macro doc to see how) or allocate vectorizable matrices only via new:

struct MyStructImpl{
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
    // vectorizable matrices ...
};

struct MyStruct
{
  MyStructImpl* aligned_data_; // possibly a unique_ptr<MyStructImpl>
  // copy-move-assign accordingly ...
  // non-vectorizable matrices and other data ...
};

std::vector<MyStruct> v; // ok !

这将花费您堆分配和更少的内存局部性,但使MyStruct到处移动会更便宜.因此,根据您的使用情况,结果可能更快或更慢.

this will cost you an heap allocation and less memory locality, but will make cheaper to move MyStruct around. So, it may turn out faster or slower, depending on your use case.

这篇关于std :: vector的对齐问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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