包含特征向量的类的奇异大小

Strange size of class containing Eigen vectors

本文关键字:特征 向量 包含      更新时间:2023-10-16

包含两个特征向量的C++类具有奇怪的大小。我在这里有我的问题的MWE:

#include <iostream>
#include "Eigen/Core"
class test0 {
Eigen::Matrix<double,4,1> R;
Eigen::Matrix<double,4,1> T;
};
class test1 {
Eigen::Matrix<double,4,1> R;
Eigen::Matrix<double,3,1> T;
};
class test2 {
Eigen::Matrix<double,4,1> R;
Eigen::Matrix<double,2,1> T;
};
class test3 {
Eigen::Matrix<double,7,1> T;
};
class test4 {
Eigen::Matrix<double,3,1> T;
};
int main(int argc, char *argv[])
{
std::cout << sizeof(test0) << ", " << sizeof(test1) << ", " << sizeof(test2) << ", " << sizeof(test3) << ", " << sizeof(test4) << std::endl;
return 0;
}

我在系统(MacBook Pro,Xcode Clang++编译器)上得到的输出是:

64、64、48、56、24

类"test1"有一些奇怪的额外填充——我本以为它的大小是56。我不明白它的原因,特别是考虑到其他类都没有任何填充。有人能解释一下吗?还是这是个错误?

这是因为Eigen库是如何实现的,并且与编译器技巧无关。Eigen::Matrix<double, 4, 1>的后备存储器上有EIGEN_ALIGN_TO_BOUNDARY(16)标记,它具有编译器特定的定义,要求类型在16字节的边界上对齐。为了确保这一点,编译器必须在结构的末尾添加8个字节的填充,否则,如果您有一个test1数组,第一个矩阵字段将不会在16字节的边界上对齐。

Eigen根本没有试图对Eigen::Matrix<double, 7, 1>的后备存储器施加类似的要求。

这种情况发生在Eigen/src/Core/DenseStorage中。

填充需求不是由语言强制要求的,它们实际上是由处理器体系结构强制要求的。您的类正在被填充,因此它有64字节宽。当然,您可以覆盖它,但这样做是为了使结构整齐地位于内存中,并且可以有效地读取,与缓存线对齐。

在什么情况下填充一个结构是一个复杂的问题,但一般来说"内存很便宜,周期不便宜"。现代计算机有大量的内存,而且随着我们接近铜的极限,性能提升变得越来越难找到,所以用一些内存换取性能通常是个好主意。

这里提供了一些额外的阅读资料。


根据评论中的讨论,值得注意的是,编译器不是你的上帝。并非每一次优化都是一个好主意,即使是对代码的微小更改也会对某些优化产生巨大影响。如果你不喜欢你的工具链生产的东西,并且认为你可以做得更好,那就去做吧!采取一些基准,做出改变,然后再次衡量。当你做所有这些的时候,不要花多长时间,然后问自己——这是对你或你的雇主时间的一种很好的利用吗?:)