speedup by transpose based multiplication
This commit is contained in:
@@ -128,7 +128,7 @@ class sp_auxlib
|
||||
inline static void run_aupd_plain
|
||||
(
|
||||
const uword n_eigvals, char* which,
|
||||
const SpMat<T>& X, const bool sym,
|
||||
const SpMat<T>& X, const SpMat<T>& Xst, const bool sym,
|
||||
blas_int& n, eT& tol, blas_int& maxiter,
|
||||
podarray<T>& resid, blas_int& ncv, podarray<T>& v, blas_int& ldv,
|
||||
podarray<blas_int>& iparam, podarray<blas_int>& ipntr,
|
||||
|
||||
@@ -479,7 +479,9 @@ sp_auxlib::eigs_sym_arpack(Col<eT>& eigval, Mat<eT>& eigvec, const SpMat<eT>& X,
|
||||
}
|
||||
else
|
||||
{
|
||||
run_aupd_plain(n_eigvals, which, X, true /* sym, not gen */, n, tol, maxiter, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork, info);
|
||||
const SpMat<eT> Xst = X.st();
|
||||
|
||||
run_aupd_plain(n_eigvals, which, X, Xst, true /* sym, not gen */, n, tol, maxiter, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork, info);
|
||||
}
|
||||
|
||||
if(info != 0) { return false; }
|
||||
@@ -863,7 +865,9 @@ sp_auxlib::eigs_gen_arpack(Col< std::complex<T> >& eigval, Mat< std::complex<T>
|
||||
}
|
||||
else
|
||||
{
|
||||
run_aupd_plain(n_eigvals, which, X, false /* gen, not sym */, n, tol, maxiter, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork, info);
|
||||
const SpMat<T> Xst = X.st();
|
||||
|
||||
run_aupd_plain(n_eigvals, which, X, Xst, false /* gen, not sym */, n, tol, maxiter, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork, info);
|
||||
}
|
||||
|
||||
if(info != 0) { return false; }
|
||||
@@ -1105,7 +1109,9 @@ sp_auxlib::eigs_gen(Col< std::complex<T> >& eigval, Mat< std::complex<T> >& eigv
|
||||
}
|
||||
else
|
||||
{
|
||||
run_aupd_plain(n_eigvals, which, X, false /* gen, not sym */, n, tol, maxiter, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork, info);
|
||||
const SpMat< std::complex<T> > Xst = X.st();
|
||||
|
||||
run_aupd_plain(n_eigvals, which, X, Xst, false /* gen, not sym */, n, tol, maxiter, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork, info);
|
||||
}
|
||||
|
||||
if(info != 0) { return false; }
|
||||
@@ -1893,7 +1899,7 @@ void
|
||||
sp_auxlib::run_aupd_plain
|
||||
(
|
||||
const uword n_eigvals, char* which,
|
||||
const SpMat<T>& X, const bool sym,
|
||||
const SpMat<T>& X, const SpMat<T>& Xst, const bool sym,
|
||||
blas_int& n, eT& tol, blas_int& maxiter,
|
||||
podarray<T>& resid, blas_int& ncv, podarray<T>& v, blas_int& ldv,
|
||||
podarray<blas_int>& iparam, podarray<blas_int>& ipntr,
|
||||
@@ -1978,30 +1984,46 @@ sp_auxlib::run_aupd_plain
|
||||
// where x is of length n and starts at workd(ipntr(0)), and y is of
|
||||
// length n and starts at workd(ipntr(1)).
|
||||
|
||||
// operator*(sp_mat, vec) doesn't properly put the result into the
|
||||
// right place so we'll just reimplement it here for now...
|
||||
// // OLD METHOD
|
||||
//
|
||||
// // operator*(sp_mat, vec) doesn't properly put the result into the
|
||||
// // right place so we'll just reimplement it here for now...
|
||||
//
|
||||
// // Set the output to point at the right memory. We have to subtract
|
||||
// // one from FORTRAN pointers...
|
||||
// Col<T> out(workd.memptr() + ipntr(1) - 1, n, false /* don't copy */);
|
||||
// // Set the input to point at the right memory.
|
||||
// Col<T> in(workd.memptr() + ipntr(0) - 1, n, false /* don't copy */);
|
||||
//
|
||||
// out.zeros();
|
||||
//
|
||||
// T* out_mem = out.memptr();
|
||||
// const T* in_mem = in.memptr();
|
||||
//
|
||||
// typename SpMat<T>::const_iterator X_it = X.begin();
|
||||
//
|
||||
// const uword X_nnz = X.n_nonzero;
|
||||
//
|
||||
// for(uword count=0; count < X_nnz; ++count, ++X_it)
|
||||
// {
|
||||
// const eT X_it_val = (*X_it);
|
||||
// const uword X_it_row = X_it.row();
|
||||
// const uword X_it_col = X_it.col();
|
||||
//
|
||||
// out_mem[X_it_row] += X_it_val * in_mem[X_it_col];
|
||||
// }
|
||||
//
|
||||
// // No need to modify memory further since it was all done in-place.
|
||||
|
||||
// Set the output to point at the right memory. We have to subtract
|
||||
// one from FORTRAN pointers...
|
||||
Col<T> out(workd.memptr() + ipntr(1) - 1, n, false /* don't copy */);
|
||||
// Set the input to point at the right memory.
|
||||
Col<T> in(workd.memptr() + ipntr(0) - 1, n, false /* don't copy */);
|
||||
|
||||
out.zeros();
|
||||
// NEW METHOD
|
||||
//
|
||||
// both operator*(rowvec, sp_mat) and operator*(sp_mat, colvec) can now write to an existing object
|
||||
|
||||
typename SpMat<T>::const_iterator X_it = X.begin();
|
||||
typename SpMat<T>::const_iterator X_it_end = X.end();
|
||||
Row<T> out(workd.memptr() + ipntr(1) - 1, n, false, true);
|
||||
Row<T> in(workd.memptr() + ipntr(0) - 1, n, false, true);
|
||||
|
||||
while(X_it != X_it_end)
|
||||
{
|
||||
const uword X_it_row = X_it.row();
|
||||
const uword X_it_col = X_it.col();
|
||||
|
||||
out[X_it_row] += (*X_it) * in[X_it_col];
|
||||
++X_it;
|
||||
}
|
||||
|
||||
// No need to modify memory further since it was all done in-place.
|
||||
out = in * Xst;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2234,9 +2256,6 @@ sp_auxlib::run_aupd_shiftinvert
|
||||
// where x is of length n and starts at workd(ipntr(0)), and y is of
|
||||
// length n and starts at workd(ipntr(1)).
|
||||
|
||||
// operator*(sp_mat, vec) doesn't properly put the result into the
|
||||
// right place so we'll just reimplement it here for now...
|
||||
|
||||
// Set the output to point at the right memory. We have to subtract
|
||||
// one from FORTRAN pointers...
|
||||
Col<T> out(workd.memptr() + ipntr(1) - 1, n, false /* don't copy */);
|
||||
|
||||
Reference in New Issue
Block a user