C++ 如何加速a+=coefs*coefs.transpose()
我需要计算一些大约400k的小型线性最小二乘问题的解。每个问题包含10-300个方程,只有7个变量。 为了解决这些问题,我使用了特征库。直接求解需要太多的时间,我通过手工推导导数,将每个问题转化为求解7x7线性方程组 我得到了很好的加速,但我想再次提高性能 我使用vagrind来分析我的程序,我发现自我成本最高的操作是特征矩阵的运算符+=运算。此操作需要十多次调用a.ldlt.solveb 我用这个算符组成每个方程组的矩阵和B向量C++ 如何加速a+=coefs*coefs.transpose(),c++,performance,matrix,eigen,eigen3,C++,Performance,Matrix,Eigen,Eigen3,我需要计算一些大约400k的小型线性最小二乘问题的解。每个问题包含10-300个方程,只有7个变量。 为了解决这些问题,我使用了特征库。直接求解需要太多的时间,我通过手工推导导数,将每个问题转化为求解7x7线性方程组 我得到了很好的加速,但我想再次提高性能 我使用vagrind来分析我的程序,我发现自我成本最高的操作是特征矩阵的运算符+=运算。此操作需要十多次调用a.ldlt.solveb 我用这个算符组成每个方程组的矩阵和B向量 //I cal these code to solve each
//I cal these code to solve each problem
const int nVars = 7;
//i really need double precision
Eigen::Matrix<double, nVars, nVars> a = Eigen::Matrix<double, nVars, nVars>::Zero();
Eigen::Matrix<double, nVars, 1> b = Eigen::Matrix<double, nVars, 1>::Zero();
Eigen::Matrix<double, nVars, 1> equationCoeffs;
//............................
//Somewhere in big cycle.
//equationCoeffs and z are updated on each iteration
a += equationCoeffs * equationCoeffs.transpose();
b += equationCoeffs * z;
其中z是一些标量
所以我的问题是:如何提高这些操作的性能
PS对不起,我的英语很差我有一个问题Ax=b和480k浮点变量。矩阵A是稀疏的,用特征BiCGSTAB求解它需要4.8秒 我以前也和ViennaCL合作过,所以我尝试在那里解决同样的问题,只花了1.2秒。spead的增加已实现
通过GPU上的处理。您可以尝试一次分配足够大的矩阵(例如300 x 7)来存储所有系数,然后让Eigen的优化矩阵积核为您完成以下工作,而不是手动形成正常方程的矩阵和向量分量:
Matrix<double,Dynamic,nbVars> D(300,nbVars);
VectorXd f(300);
for(...)
{
int nb_equations = ...;
for(i=0..nb_equations-1)
{
D.row(i) = equationCoeffs;
f(i) = z;
}
a = D.topRows(nb_equations).transpose() * D.topRows(nb_equations);
b = D.topRows(nb_equations).transpose() * f.head(nb_equations);
// solve ax=b
}
您可以使用列主存储区和行主存储区对矩阵D进行测试,以确定哪一个是最好的
另一种可能的方法是将a、方程系数和b声明为8x8或8x1矩阵或向量,确保方程系数7==0。这样可以最大限度地利用SIMD。然后在调用LDLT时使用a.topLeftCorners和b.head。您甚至可以将此策略与前一个策略相结合
最后,如果您的CPU支持AVX或FMA,您可以使用devel分支并使用-mavx或-mfma进行编译,以获得显著的加速。如果您可以使用g++5.1,您可能需要看看OpenMP . G++5.1或gcc5.1forC也有一些对OpenACC的基本支持,您也可以尝试一下。未来应该有更多的OpenACC实现 此外,如果您可以访问英特尔编译器icc,icpc,它甚至可以通过使用它来加速我的代码 如果您可以使用nvidia的nvcc,您可以使用推力库 ,他们的github上也有很多示例代码 . 然而,使用推力并不是那么直截了当,需要一些真正的思考 编辑: 推力还需要Nvidia GPU。
对于AMD卡,我相信有一个名为ArrayFire的库,它看起来非常类似于我没有尝试过的推力,但谢谢您的回答。但我有很多非常小的密集问题,而不是一个大而稀疏的问题。我现在也不能使用GPU=谢谢你的回答!看起来很有趣。我将尝试使用大型矩阵的方法。我以前也试过使用8x8/8x1矩阵,但它并没有给我加速。谢谢你们的回答。我无法使用像icc这样的高级编译器。但也许我会尝试使用openmp。此外,我认为可以将openmp与旧版本的gcc一起使用