将特征类型与 STL 容器和 std::vector 一起使用

Shi*_*hah 5 c++ vectorization eigen c++11 eigen3

看起来将 Eigen 类型与 STL 容器一起使用非常混乱,需要特别注意对齐问题。我的问题是我计划创建具有数十个类的复杂类层次结构,这些类可能包含一个或多个特征类型作为成员变量。从文档看来,只要您在成员变量中包含 Eigen 类型,您的类就会“感染”与 Eigen 类型相同的问题。这意味着我必须格外小心地使用 STL 容器,不仅用于 Eigen 类型,而且还用于我所有的几十个类。

让我担心的更糟糕的部分是,任何在他们的代码中使用我的类的实例的人都会遇到同样的问题,并且需要成为这方面的专家——即使我的类没有在他们的公共接口中公开任何特征类型!

这很令人沮丧。我的问题,

  1. 我上面的理解是否正确(我只需要支持 C++11 和现代编译器)?
  2. 有没有人们使用的任何模式,这样他们就不必在所有地方使用特殊的 Eigen 处理来污染他们的代码?
  3. 我正在考虑在全球范围内禁用整个矢量化。这会以性能为代价解决上述问题吗?是否可以仅针对特定代码有选择地启用?
  4. 如果我忘记处理代码中某处的对齐问题,我是否总是得到编译时错误或问题可能仍然隐藏并且在运行时可能会崩溃?

gga*_*ael 5

是你的理解大多是正确的,但我要补充一点,这仅涉及本征的需要这种排列为固定大小类型Vector4fMatrix2d等等。但不能Vector3fMatrixXd。此外,问题的核心是 STL 容器还不alignas满足要求,尽管这应该会出现在未来的 C++ 版本中。

我认为避免这种困难的最简单方法是对类成员和容器值类型使用非对齐的特征类型,例如:

typedef Eigen::Matrix<float,4,1,Eigen::DontAlign> UVector4f;
typedef Eigen::Matrix<double,2,2,Eigen::DontAlign> UMatrix2d;
Run Code Online (Sandbox Code Playgroud)

这样您就不必担心对齐问题,也不会丢失显式矢量化。在 Eigen 3.3 中,未对齐的对象也被矢量化。

编辑:

关于你的最后一个问题,不幸的是,在 C++ 中不可能在编译时检测到这样的缺点。如果断言未被禁用并且在运行时发生了无效的未对齐分配,那么您将收到一条明确的断言消息,但这就是我们所能做的。因此,如果您的程序在具有某些给定编译标志的给定系统上运行良好,那么这并不意味着您的代码是安全的。例如,在大多数 64 位系统上,缓冲区在 16 字节边界上对齐,因此,如果您不启用 AVX 指令集,那么您的代码将运行良好。另一方面,如果移动到更奇特的平台,或者启用默认情况下需要 32 字节对齐的 AVX 指令,则相同的代码可能会断言。尽管如此,静态分析器正变得越来越强大,

另一种策略包括使用malloc仅返回 8 字节对齐缓冲区的自定义检查您的程序。通过这种方式,您应该能够发现所有缺点,假设您的程序已被单元测试很好地覆盖。为此-DEIGEN_MALLOC_ALREADY_ALIGNED=0,出于显而易见的原因,您必须使用 进行编译。