当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

Eigen库:那些年我们一起经历的bug

发表于: 2014-09-24   作者:cherishLC   来源:转载   浏览次数:
C++
摘要: 1、使用auto声明新变量时不要局部eval() 这句话神马意思呢? 我们知道,在C++函数中最好不要返回局部变量,否则可能产生因为局部变量被回首而引发的错误。 而这个问题正是源于此。 在以下这个bug中: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=505  “a*b”就会引发自动的eval(),从而产生局部变量,该局部变量
1、使用auto声明新变量时不要局部eval()
这句话神马意思呢? 我们知道,在C++函数中最好不要返回局部变量,否则可能产生因为局部变量被回首而引发的错误。
而这个问题正是源于此。
在以下这个bug中:
http://eigen.tuxfamily.org/bz/show_bug.cgi?id=505 
“a*b”就会引发自动的eval(),从而产生局部变量,该局部变量被一个表达式所引用,导致结果不可预知。
最新版本的Eigen已经解决了这个问题~~~那么,这个bug是不是完全不存在了呢?
答案是NO。。。。
看以下的代码:

    auto A_mul_B_plus_C = C + (A * B).colwise().sum();
    auto A_mul_B_Eval_plus_C = C + (A * B).colwise().sum().eval();

二者的结果都是表达式,但是第二个表达式中局部变量被eval()了,产生了一个临时的Matrix,该临时变量会被回收,导致结果的不正确。
解决方案:
  • 1、不使用auto A_mul_B_Eval_plus_C,而是使用MatrixXd A_mul_B_Eval_plus_C这类的显式声明。(但这样不够灵活有没有!)
  • 2、使用eval(),对,你没看错,但是是在整条语句上使用eval();比如:auto A_mul_B_plus_C_EvalAll = (C + (A * B).colwise().sum().eval() ).eval(); //如果该变量要多次使用,推荐这种做法,这种做法也是最安全的(不会因为Eigen库还有之前a*b产生局部变量引发的错误)
  • 3、完全不使用eval(); 比如:auto A_mul_B_plus_C = C + (A * B).colwise().sum();

完整的代码参见: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=883
更深入了解这个bug看下面这个链接: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=99

2、不用eval()也是不行的!(最新版本(3.2.2)不存在这个问题了)
也许你会有所疑问,我干嘛要手动eval()呢?
这源于另一个bug:
一年前接触Eigen库的时候,写过这么一段代码

      Eigen::MatrixXd m=Eigen::MatrixXd::Ones(3,4);
      m.array().rowwise()/=m.array().colwise().sum();
      std::cout<<m<<std::endl;

结果大跌眼镜(最新版本的输出没问题了):
  • 0.333333 0.333333 0.333333 0.333333
  • 0.428571 0.428571 0.428571 0.428571
  • 0.567568 0.567568 0.567568 0.567568

原因可能是等号右边时表达式,左边每行除以右边时,右边的表达式都会被重新计算。。。
所以当时的版本必须eval()一下!好在现在这个bug消除了!
另外多说一句,基于效率考虑,可能也要eval()一下,但是我调了下代码,当前版本的Eigen右侧的表达式是只计算一遍的,放心的不eval()吧!

Eigen库:那些年我们一起经历的bug

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
回顾四年,四年的蜕变。记得有一次在CSDN有个这样的讨论 我的回答是: 别人讽刺的说我农民造飞机,
一、清除浮动 还是 闭合浮动 (Enclosing float or Clearing float)? 很多人都已经习惯称之为清除
浮动(float),一个我们即爱又恨的属性。爱,因为通过浮动,我们能很方便地布局; 恨,浮动之后遗留
什么是浮动? 原理: 在css中使用float:left和float:right,使元素脱离文档流。同时显示为类似displa
1.2013-12-17 10:38:47.205 一类调查[666:a0b] *** Assertion failure in -[UITableView _endCellAn
还记得两年前的昨天和前天,我们一起征战沙场,一起为了未来奋斗着,努力着。可是这些俨然成为历史
浮动(float),一个我们即爱又恨的属性。爱,因为通过浮动,我们能很方便地布局; 恨,浮动之后遗留
mmap设备方法) Mmap系统调用(功能) Void* mmap(void * add, size_t len , int prot, int flags,
浮动(float),一个我们即爱又恨的属性。爱,因为通过浮动,我们能很方便地布局; 恨,浮动之后遗留
那些年,我们一起合作时头痛的事 浏览次数: 523次 2012年04月21日 腾讯CDC 字号: 大 中 小 分享到
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号