[Eigen中文文档] 编译器对堆栈对齐做出了错误的假设

简介: 本文将介绍编译器对堆栈对齐做出了错误的假设问题。

文档总目录

英文原文(Compiler making a wrong assumption on stack alignment)

这是 GCC 的错误,已在 GCC 4.5 中修复。如果遇到此问题,请升级到 GCC 4.5

到目前为止,我们只在 Windows 上遇到过 GCC:例如,MinGW 和 TDM-GCC。

默认情况下,在类似如下函数中:

void foo()
{
   
  Eigen::Quaternionf q;
  //...
}

GCC 假定堆栈已经是 16 字节对齐的,因此对象 q 将在 16 字节对齐的位置创建。根据 Eigen 的要求,不需要特别注意显式对齐对象 q

问题是,在某些特定情况下,这种假设在 Windows 上可能是错误的,其中堆栈只保证 4 字节对齐。 实际上,即使 GCC 负责对齐 main 函数中的堆栈并尽最大努力保持其对齐,但当从另一个线程或从使用另一个编译器编译的二进制文件调用函数时,堆栈对齐可能会被破坏。这会导致在未对齐的位置创建对象 q,从而使程序因对未对齐数组断言而崩溃。至此我们找到了以下解决方案。

局部解决方案

局部解决方案是使用此属性标记此类功能:

__attribute__((force_align_arg_pointer)) void foo()
{
   
  Eigen::Quaternionf q;
  //...
}

阅读 GCC 文档 以了解其作用。当然,这只能在 Windows 上的 GCC 上完成,因此为了可移植性,必须将其封装在一个宏中,并在其他平台上设置该宏为空。此解决方案的优点是可以精确地选择哪个函数可能具有损坏的堆栈对齐。当然,不利的一面是必须为每个此类功能完成此操作,因此可能更喜欢以下两种全局解决方案之一。

全局解决方案

一个全局解决方案是在 Windows 上使用 GCC 进行编译时,使用如下选项:

-mincoming-stack-boundary=2

这告诉 GCC 堆栈只需要对齐到 2^2=4 字节,因此 GCC 现在知道它确实必须格外小心,以便在需要时遵守固定大小的可向量化 Eigen 类型的 16 字节对齐。

另一个全局解决方案是使用如下选项:

-mstackrealign

这与将 force_align_arg_pointer 属性添加到所有函数具有相同的效果。

这些全局解决方案易于使用,但请注意它们可能会损耗程序效率,因为它们会导致每个函数都有额外的序言/结尾说明。

相关文章
|
编译器 索引
[Eigen中文文档] 块操作
本文介绍了块操作。块是matrix或array的部分矩形元素。块表达式既可以用作右值也可以用作左值。与Eigen表达式一样,如果让编译器进行优化,则块操作的运行时间成本为零。
499 0
|
存储 算法 NoSQL
[Eigen中文文档] 存储顺序
矩阵和二维数组有两种不同的存储顺序:列优先和行优先。本节解释了这些存储顺序以及如何指定应该使用哪一种。
716 0
|
存储 编译器 C语言
[Eigen中文文档] 对未对齐数组断言的解释
本文将解释程序因断言失败而终止的问题。
579 0
|
存储 算法 NoSQL
[Eigen中文文档] 稀疏矩阵操作
在许多应用中(例如,有限元方法),通常要处理非常大的矩阵,其中只有少数系数不为零。在这种情况下,可以通过使用仅存储非零系数的特殊表示来减少内存消耗并提高性能。这样的矩阵称为稀疏矩阵。
1066 0
|
存储 C语言 C++
|
安全 编译器 C++
[Eigen中文文档] 矩阵与向量运算
本文章旨在提供有关如何使用 Eigen 在矩阵、向量和标量之间执行算术操作的概述和一些详细信息。
1077 0
|
编译器 API 索引
[Eigen中文文档] 切片和索引
本文介绍了如何使用操作运算符operator()索引行和列的子集。该 API 在 Eigen 3.4 中引入。它支持 block API 提供的所有功能。特别是,它支持切片,即获取一组行、列或元素,以及等间隔的从矩阵或者数组中提取元素。
865 0
|
存储 C++
[Eigen中文文档] 原始缓冲区接口:Map 类
本节解释了如何使用“原始”C/C++ 数组。这在各种情况下都很有用,特别是在将向量和矩阵从其他库“导入”到 Eigen 中时。
520 0
[Eigen中文文档] 高级初始化
本文介绍了几种用于初始化矩阵的高级方法。提供了有关之前介绍的逗号初始化程序的更多详细信息。还解释了如何获得特殊矩阵,例如单位矩阵和零矩阵。
503 0
|
存储 JavaScript 索引
[Eigen中文文档] 归约、访问者和广播
本文介绍了Eigen的归约、访问者和广播,以及它们如何与矩阵和数组一起使用。
543 0