这是因为 Eigen 将代码显式矢量化为剩余 4 个分量寄存器内的 3 个 vmulpd、2 个 vaddpd 和 1 个水平缩减(假设 AVX,仅使用 SSE,您将获得 6 个 mulpd 和 5 个 addpd)。和-ffast-math
GCC 和 clang 被允许删除最后 2 个 vmulpd 和 vaddpd (这就是他们所做的),但它们不能真正取代 Eigen 显式生成的剩余 vmulpd 和水平缩减。
那么,如果您通过定义禁用 Eigen 的显式矢量化会怎么样?EIGEN_DONT_VECTORIZE
?然后你就得到了你所期望的(https://godbolt.org/z/UQsoeH https://godbolt.org/z/UQsoeH)但其他代码片段可能会变得慢得多。
如果你想在本地禁用显式矢量化并且不怕弄乱 Eigen 的内部,你可以引入一个DontVectorize
选项Matrix
并通过专门化禁用矢量化traits<>
为了这Matrix
type:
static const int DontVectorize = 0x80000000;
namespace Eigen {
namespace internal {
template<typename _Scalar, int _Rows, int _Cols, int _MaxRows, int _MaxCols>
struct traits<Matrix<_Scalar, _Rows, _Cols, DontVectorize, _MaxRows, _MaxCols> >
: traits<Matrix<_Scalar, _Rows, _Cols> >
{
typedef traits<Matrix<_Scalar, _Rows, _Cols> > Base;
enum {
EvaluatorFlags = Base::EvaluatorFlags & ~PacketAccessBit
};
};
}
}
using ArrayS12d = Eigen::Matrix<double,12,1,DontVectorize>;
完整的例子在那里:https://godbolt.org/z/bOEyzv https://godbolt.org/z/bOEyzv