简体   繁体   English

如何加速C ++稀疏矩阵操作?

[英]How to speed up a C++ sparse matrix manipulation?

I have a small script for manipulating a sparse matrix in C++. 我有一个小脚本用于在C ++中操作稀疏矩阵。 It works perfectly fine except taking too much time. 除了花费太多时间外,它的工作原理非常好。 Since I'm doing this manipulation over and over, it is critical to speed it up. 由于我一遍又一遍地进行这种操作,因此加速它是至关重要的。 I appreciate any idea.Thanks 我很感激。谢谢

#include <stdio.h>      /* printf, scanf, puts, NULL */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */
#include <iostream>     /* cout, fixed, scientific */
#include <string>
#include <cmath>
#include <vector>
#include <list>
#include <string>
#include <sstream>      /* SJW 08/09/2010 */
#include <fstream>
#include <Eigen/Dense>
#include <Eigen/Sparse>

using namespace Eigen;
using namespace std;

SparseMatrix<double> MatMaker (int n1, int n2, double prob)
{
   MatrixXd A = (MatrixXd::Random(n1, n2) + MatrixXd::Ones(n1, n2))/2;
   A = (A.array() > prob).select(0, A);
   return A.sparseView();
}

////////////////This needs to be optimized/////////////////////
int SD_func(SparseMatrix<double> &W, VectorXd &STvec, SparseMatrix<double>   &Wo, int tauR, int tauD)
{
W = W + 1/tauR*(Wo - W); 
for (int k = 0; k < W.outerSize(); ++k)
    for (SparseMatrix<double>::InnerIterator it(W, k); it; ++it)
        W.coeffRef(it.row(),it.col()) = it.value() * (1-STvec(it.col())/tauD);

return 1;
}


int main ()
{
SparseMatrix<double> Wo = MatMaker(5000, 5000, 0.1);
SparseMatrix<double> W = MatMaker(5000, 5000, 0.1);
VectorXd STvec = VectorXd::Random(5000);

clock_t tsd1,tsd2;
float Timesd = 0.0;
tsd1 = clock();

///////////////////////////////// Any way to speed up this function???????
SD_func(W, STvec, Wo, 8000, 50);
//////////////////////////////// ??????????

tsd2 = clock();
Timesd += (tsd2 - tsd1);

cout<<"SD time: " << Timesd / CLOCKS_PER_SEC << " s" << endl;

return 0;
}

The most critical performance improvement (IMO) you can make is to not use W.coeffRef(it.row(),it.col()) . 您可以做的最关键的性能改进(IMO)是不使用W.coeffRef(it.row(),it.col()) It performs a binary search in W for the element each time. 它每次都在W中对元素执行二进制搜索。 As you are already using SparseMatrix<double>::InnerIterator it(W, k); 因为你已经在使用SparseMatrix<double>::InnerIterator it(W, k); it is very simple to change your function to skip the binary search: 更改函数以跳过二进制搜索非常简单:

int SD_func_2(SparseMatrix<double> &W, VectorXd &STvec, SparseMatrix<double>   &Wo, int tauR, int tauD)
{
    W = W + 1/tauR*(Wo - W);
    double tauDInv = 1./tauD;
    for (int k = 0; k < W.outerSize(); ++k)
        for (SparseMatrix<double>::InnerIterator it(W, k); it; ++it)
            it.valueRef() *= (1-STvec(it.col())*tauDInv);

    return 1;
}

This results in a roughly x3 speedup. 这导致大约x3加速。 Note that I've incorporated @dshin's comment that multiplying is faster than division, however the performance improvement is about 90% removing the binary search, 10% multiplication vs. division. 请注意,我已经合并了@dshin的评论 ,即乘法比分割更快,但是性能提升大约是90%,删除二进制搜索,10%乘法与除法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM