Eigen 內由於斷言失敗而終止的打印信息類似如下
program: path/to/eigen/Eigen/src/Core/DenseStorage.h:44:
Eigen::internal::matrix_array<T, Size, MatrixOptions, Align>::internal::matrix_array()
[with T = double, int Size = 2, int MatrixOptions = 2, bool Align = true]:
Assertion `(reinterpret_cast<size_t>(array) & (sizemask)) == 0 && "this assertion
is explained here: http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html
READ THIS WEB PAGE !!! ****"' failed.
Eigen 官方給出的解決地址:http://eigen.tuxfamily.org/dox/TopicUnalignedArrayAssert.html
國內博客漢語版的翻譯地址:https://blog.csdn.net/qq_27806947/article/details/105356401
解決方式根據產生原因不同分為四類
eigen類型是成員變量
class Foo
{
//...
Eigen::Vector2d v;
//...
};
//...
Foo *foo = new Foo;
解決策略:Structures Having Eigen Members
請注意,此處Eigen :: Vector2d僅用作示例,更一般而言,所有fixed-size vectorizable Eigen types都會出現此問題。
STL容器或手動分配內存(new)
如果您將stl容器(例如std::vector,std::map等)與Eigen對象或包含Eigen對象的類一起使用,
std::vector<Eigen::Matrix2f> my_vector;
struct my_class { ... Eigen::Matrix2f m; ... };
std::map<int, my_class> my_map;
那么您需要閱讀以下單獨的頁面:STL容器與Eigen結合使用。
請注意,此處Eigen::Matrix2f僅用作示例,更一般而言,對於所有fixed-size vectorizable Eigen types和structures having such Eigen objects as member,都會出現此問題。
值傳遞eigen對象
如果您代碼中的某些函數正在通過值傳遞Eigen對象,例如這樣,
void func(Eigen::Vector4d v);
那么您需要閱讀以下單獨的頁面:將Eigen對象按值傳遞給函數。
編譯器對堆棧對齊做出錯誤假設(例如Windows上的GCC)
這是在Windows上使用GCC(例如MinGW或TDM-GCC)的人們的必讀內容。If you have this assertion failure in an innocent function declaring a local variable like this:
void foo()
{
Eigen::Quaternionf q;
//...
}
then you need to read this separate page: Compiler making a wrong assumption on stack alignment.
請注意,此處Eigen :: Quaternionf僅用作示例,更一般而言,所有fixed-size vectorizable Eigen types都會出現此問題。
斷言的一般解釋
fixed-size vectorizable Eigen types必須絕對在16字節對齊的位置創建,否則尋址它們的SIMD指令將崩潰。
Eigen normally takes care of these alignment issues for you, by setting an alignment attribute on them and by overloading their "operator new".However there are a few corner cases where these alignment settings get overridden: they are the possible causes for this assertion.
不在乎最佳矢量化,如何禁止向量優化
三種可能性
- 使用Matrix,Array,Quaternion等對象的DontAlign選項會給您帶來麻煩。這樣,Eigen不會嘗試對齊它們,因此不會承擔任何特殊的對齊。On the down side, you will pay the cost of unaligned loads/stores for them, but on modern CPUs, the overhead is either null or marginal. See here for an example.
- Define EIGEN_DONT_ALIGN_STATICALLY . That disables all 16-byte (and above) static alignment code, while keeping 16-byte (or above) heap alignment. This has the effect of vectorizing fixed-size objects (like Matrix4d) through unaligned stores (as controlled by EIGEN_UNALIGNED_VECTORIZE), while keeping unchanged the vectorization of dynamic-size objects (like MatrixXd). But do note that this breaks ABI compatibility with the default behavior of static alignment.
- 或同時定義EIGEN_DONT_VECTORIZE和EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT。這樣可以
保留16字節的對齊代碼,從而保留ABI兼容性,但完全禁用向量化
。
如果您想知道為什么定義EIGEN_DONT_VECTORIZE本身並不能禁用16字節對齊和斷言,則說明如下:
它不會禁用斷言,because otherwise code that runs fine without vectorization would suddenly crash when enabling vectorization. 它不會禁用16字節對齊,因為這將意味着矢量化和非矢量化的代碼ABI不兼容。即使對於僅開發內部應用程序的人,這種ABI兼容性也非常重要,as for instance one may want to have in the same application a vectorized path and a non-vectorized path.