【问题标题】:BOOST uBLAS matrix product extremely slowBOOST uBLAS 矩阵积极慢
【发布时间】:2011-10-17 19:05:42
【问题描述】:

有没有办法提高boost ublas产品的性能?

我有两个矩阵 A,B 我想乘/加/子/...

在 MATLAB 与 C++ 中,对于 2000x2000 矩阵运算,我得到以下时间 [s]

OPERATION | MATLAB | C++ (MSVC10)
A + B     |  0.04  |  0.04
A - B     |  0.04  |  0.04
AB        |  1.0   | 62.66
A'B'      |  1.0   | 54.35

为什么这里会有如此巨大的性能损失?

矩阵只是真正的双精度数。 但我也需要正定、对称、矩形乘积。

编辑: 代码很简单

matrix<double> A( 2000 , 2000 );
// Fill Matrix A
matrix<double> B = A;

C = A + B;
D = A - B;
E = prod(A,B);
F = prod(trans(A),trans(B));

编辑 2: 结果是 10 次尝试的平均值。标准差小于 0.005

我预计系数可能是 2-3,但不是 50(!)

编辑 3: 一切都在发布 (NDEBUG/MOVE_SEMANTICS/..) 模式下进行。

编辑 4: 产品结果的预分配矩阵不影响运行时间。

【问题讨论】:

  • 一定要重新运行一个干净的 Matlab,它往往会缓存......好吧,一切。完全不相关,但您应该能够从Eigen 获得不错的性能和简单的语法。 (我很感兴趣它与您的小基准有何关系,提示提示 :-)
  • 我预计乘法与加法的时间约为 2000 倍..
  • 你记得打开uBlas的发布模式吗?请参阅 [link=boost.org/doc/libs/1_47_0/libs/numeric/ublas/doc/… 末尾的常见问题解答,这表明您需要具有“-DNDEBUG”或其他一些标志才能使 ublas 编译发布。
  • 你不知道内存管理在这里扮演什么角色。 prod 必须分配一个 32mb 的矩阵,trans 也是如此,两次,然后你就做了 10 次。拿几个stackhots 看看它真正在做什么。我愚蠢的猜测是,如果您预先分配矩阵,您会得到更好的结果。
  • @Mike - ublas 使用表达式模板,因此预分配不太可能使事情变得更快,除非编码员故意浪费矩阵副本(这里不是这种情况)。

标签: c++ performance boost ublas boost-ublas


【解决方案1】:

发布您的 C+ 代码以获取有关任何可能优化的建议。

但是您应该知道,Matlab 对其设计任务高度专业化,您不太可能使用 Boost 来匹配它。另一方面 - Boost 是免费的,而 Matlab 绝对不是。

我相信通过将 uBlas 代码绑定到底层 LAPACK 实现,可以获得最佳的 Boost 性能。

【讨论】:

  • +1 "我相信通过将 uBlas 代码绑定到底层 LAPACK 实现,可以获得最佳的 Boost 性能。" 这才是真正的答案。
【解决方案2】:

您应该在矩阵乘法的左侧使用noalias,以消除不必要的副本。

noalias(E) = prod(A,b);代替E = prod(A,B);

来自文档:

如果你确定左手表情和右手 表达式没有公共存储,则赋值没有别名。一种 在这种情况下可以指定更有效的分配:noalias(C) = prod(A, B); 这避免了创建临时矩阵 在正常作业中需要。 'noalias' 分配要求 左右手边尺寸一致。

【讨论】:

    【解决方案3】:

    有许多高效的 BLAS 实现,例如 ATLAS、gotoBLAS、MKL,请使用它们来代替。

    我不选择代码,但猜测 ublas::prod(A, B) 使用三循环,没有块且缓存不友好。如果这是真的,prod(A, B.trans()) 会比其他人快得多。

    如果 cblas 可用,则使用 cblas_dgemm 进行计算。如果没有,您可以简单地重新排列数据,即 prod(A, B.trans()) 代替。

    【讨论】:

      【解决方案4】:

      您不知道内存管理在这里扮演什么角色。 prod 必须分配一个 32mb 的矩阵,trans 也是如此,两次,然后你做了 10 次。拿几个stackhots 看看真正在做什么。我愚蠢的猜测是,如果您预先分配矩阵,您会得到更好的结果。

      其他可以加速矩阵乘法的方法是

      • 预转置左侧矩阵,以便缓存友好,并且

      • 跳过零。仅当 A(i,k) 和 B(k,j) 均非零时,才会贡献任何值。

      这是否在 uBlas 中完成是任何人的猜测。

      【讨论】:

      • 我很确定 boost ublas 使用表达式模板来避免这种情况(或者至少应该这样做)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多