C ++特征库 - 二次规划,固定与动态,性能

时间:2012-11-15 17:07:11

标签: c++ optimization eigen quadratic

我正在研究做一些二次规划,并且看过不同的库。我已经看到了QuadProg ++的各种Eigen变体(KDE ForumsBenjamin StephensStackOverflow posts)。就像测试一样,我在wingsit's Eigen variant上提供了GitHub,以实现编译时大小的问题,以通过模板来衡量性能。

我发现我在模板情况下的性能比来自wingsit代码的动态大小(MatrixXD / VectorXD)更差。我知道这不是一个简单的问题,但任何人都可以看到这可能是什么原因吗?

注意:我确实需要增加问题大小/迭代次数,我会尽可能发布。

编辑:我在Ubuntu 12.04上使用GCC 4.6.3。这些是我正在使用的标志(从wingsit的代码修改):

CFLAGS  = -O4 -Wall -msse2 -fopenmp      # option for obj
LFLAGS  = -O4 -Wall -msse2 -fopenmp      # option for exe (-lefence ...)

1 个答案:

答案 0 :(得分:3)

随着大小变大,静态大小代码的好处通常会减少。静态大小代码的典型优点主要包括(但不限于)以下内容:

  • 基于堆栈的分配,比堆分配快。但是,在大尺寸下,基于堆栈的分配不再可行(堆栈溢出),甚至从预取和参考局部的角度来看也是有益的。
  • 循环展开,当编译器看到一个小的静态大小的循环时,它可以只展开它,并可能使用SSE指令。这不适用于较大尺寸。

换句话说,对于小尺寸(可能N = 12左右),静态大小的代码可以比等效的动态大小的代码更好更快,只要编译器相当积极地进行 - 衬里和循环展开。但是,当尺寸较大时,没有意义。

此外,静态大小的代码也存在许多缺点:

  • 没有有效的移动语义/交换/写时复制策略,因为这样的代码通常用静态数组实现(为了获得上面提到的好处),这些数据不能简单地交换(如交换内部指针)
  • 包含散布功能的较大可执行文件。假设您有一个函数模板来乘以两个矩阵,因此,为每个大小组合生成一个新的编译函数(内联或不内联)。然后,你有一些算法可以进行大量的矩阵乘法,好吧,每次乘法都必须跳转到(或执行内联)该大小组合的特化。最后,你最终会得到更多需要缓存的代码,然后,缓存未命中变得更加频繁,这将完全破坏算法的性能。

因此,从中得出的教训是仅对像2到6维向量或矩阵这样的小事使用静态大小的向量和矩阵。但除此之外,最好使用动态大小的代码(或者尝试使用静态大小的代码,但要验证它的性能更好,因为不能保证这样做)。因此,我建议您重新考虑使用静态大小代码解决更大问题的想法。