具有Eigen3的C ++的最高精度

时间:2016-09-12 08:07:09

标签: c++ gcc eigen eigen3

我使用了很棒的Eigen3库来编写MATLAB MEX文件。但即使使用long double,我也遇到了一些准确性问题(与MATLAB相比)。 最关键的计算似乎是我根据正态分布计算概率的计算。 以下是代码段:

p.fill( 1/( M_PIl * sigma * sigma ) );
p.array() *= ( - 0.5/pow( sigma, 2.0 ) * ( mu.array() - x.array() ).array().square() ).array().exp();

其中xpmuEigen::Matrix< long double, Dynamic, 1 >。通常这些向量的长度为3000

我可以采取哪些步骤来获得最大可能的精度? 我可以使用哪些正确的GCC编译器标志来尽可能强制80位精度?

P.S:我使用gcc 4.9编译C ++代码(在带有MEX的MATLAB中),我的linux报告了以下可用指令集:Intel MMX,Intel SSE,Intel SSE2,Intel SSE3,Intel SSE4

编辑: 我尝试了下面的@Avi Ginsburg建议并使用以下命令编译它:

mex -g -largeArrayDims '-I/usr/include/eigen3' CXXFLAGS='-DEIGEN_DONT_VECTORIZE -std=c++11 -fPIC' test.cpp

使用doublelong double,这些选项中的每一个都给出了与MATLAB解决方案相同的错误。

3 个答案:

答案 0 :(得分:2)

我在这里猜测。您正在使用SSE指令进行数组计算,最值得注意的是...array().exp()。我非常确定SSE没有扩展的精度,因此MATLAB和Eigen之间存在差异。

答案 1 :(得分:1)

默认情况下,Eigen使用几种数学函数(包括指数函数)的更快但稍微不准确的实现。您可以通过使用-DEIGEN_FAST_MATH=0选项进行编译来显式禁用这些优化。

如果您使用gcc作为编译器,请确保不使用-Ofast-ffast-math选项,因为这会导致精度降低。

答案 2 :(得分:1)

如果要计算(1维)normal distribution的概率密度,开头的因子应为1/std::sqrt( 2* M_PIl * sigma * sigma )

此外,代码段开头的p.fill()效率低下。只需将其写在一行:

p = (1/std::sqrt(2*M_PIl*sigma*sigma)) *
      ( -0.5/(sigma*sigma) * (mu-x).array().square() ).exp();

N.B。:如果您只对阵列执行逐元素操作,请考虑将它们声明为Eigen::Array<...>而不是Eigen::Matrix<...>。模板参数是相同的,二进制布局也是相同的,但是每次要进行逐元素操作时都不需要编写.array()