BOOST uBLAS矩阵产品速度极慢

BOOST uBLAS matrix product extremely slow

本文关键字:速度 uBLAS BOOST      更新时间:2023-10-16

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

我有两个矩阵A,B,我想将它们相乘/相加/减除/…

在MATLAB与c++中,我得到以下次数[s]对于2000x2000矩阵操作

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:所有东西都在Release (NDEBUG/MOVE_SEMANTICS/…)模式。

编辑4:为乘积结果预先分配的矩阵不影响运行时。

张贴你的C+代码以获得任何可能的优化建议。

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

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

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

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

从文档:

如果你确定左手表达式和右手表达式表达式没有公共存储,那么赋值就没有混叠。一个在这种情况下,可以指定更有效的赋值:noalias(C) =prod(A, B);这避免了创建一个临时矩阵在一个正常的任务中是必需的。'noalias'任务要求这样做左右两侧尺寸一致

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

我不挑代码,但猜测ublas::prod(A, B)使用三个循环,没有块,不缓存友好。如果这是真的,prod(A, B.trans())将比其他更快。

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

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

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

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

  • 跳过零。

  • 只有当A(i,k)和B(k,j)都非零时,才有贡献值。

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