Rlinsolve is a collection of iterative solvers for (sparse) linear system of equations. It heavily relies on two popular packages, RcppArmadillo for speeding up computation and Matrix for sparse matrix support.
Introducing RcppArmadillo simply added computational boost. Let’s check by comparing with some basic approaches.
and simulate 10000 x 500 system matrix for normal equation form.
A = matrix(rnorm(10000*50),nrow=10000)
x = matrix(rnorm(50))
b = A%*%x
First example is to use a default solve
function from R base.
# for SOLVE in R base, it needs to be transformed into normal equation form.
Anormal = t(A)%*%A
bnormal = t(A)%*%b
microbenchmark(solve(Anormal,bnormal))
## Unit: microseconds
## expr min lq mean median uq max
## solve(Anormal, bnormal) 75.297 76.0715 81.21024 76.4845 77.1555 443.356
## neval
## 100
Let’s compare other available packages(pcg
and optR
) and their computation time,
microbenchmark(pcg(Anormal,bnormal),
optR(A,b,method="gauss"),
times=10)
## Unit: microseconds
## expr min lq mean median
## pcg(Anormal, bnormal) 176.393 197.616 1684.421 210.376
## optR(A, b, method = "gauss") 135359.688 135852.412 160230.685 136611.512
## uq max neval
## 238.435 14805.32 10
## 144393.710 276537.06 10
Finally, let’s test two functions in our package, lsolve.bicgstab and lsolve.sor,
microbenchmark(lsolve.sor(A,b,verbose=FALSE),
lsolve.bicgstab(A,b,verbose=FALSE),
times=10)
## Unit: milliseconds
## expr min lq mean
## lsolve.sor(A, b, verbose = FALSE) 26.21710 27.14054 39.49382
## lsolve.bicgstab(A, b, verbose = FALSE) 26.71988 27.49502 31.83477
## median uq max neval
## 27.87296 30.05976 101.44159 10
## 27.85354 28.14653 68.45279 10
where we can witness that our codes are definitely faster by at least several folds.
We have an auxiliary function to generate sparse system matrix, aux.fisch
, and let’s make a 100 x 100 sparse matrix, and corresponding system.
Psparse = aux.fisch(10,sparse=TRUE) # sparse matrix
Pdense = aux.fisch(10,sparse=FALSE) # dense matrix
x = matrix(rnorm(100))
b = Pdense %*% x
Again, we perform the test from previously used functions from other packages as well as functions in Rdimtools package,
microbenchmark(solve(Pdense,b),
optR(Pdense,b,method="gauss"),
pcg(Pdense,b),
times=10)
## Unit: microseconds
## expr min lq mean
## solve(Pdense, b) 283.198 290.888 329.1776
## optR(Pdense, b, method = "gauss") 72135.468 73038.835 75592.4082
## pcg(Pdense, b) 933.511 969.669 1032.7257
## median uq max neval
## 323.8145 362.320 413.387 10
## 74830.3290 78222.845 80787.320 10
## 998.1805 1047.926 1354.509 10
microbenchmark(lsolve.bicg(Psparse,b,verbose=FALSE),
lsolve.cgs(Psparse,b,verbose=FALSE),
lsolve.gs(Psparse,b,verbose=FALSE),
lsolve.sor(Psparse,b,verbose=FALSE),
times=10)
## Unit: milliseconds
## expr min lq mean
## lsolve.bicg(Psparse, b, verbose = FALSE) 20.78553 21.51531 26.53134
## lsolve.cgs(Psparse, b, verbose = FALSE) 16.83871 17.30754 22.38803
## lsolve.gs(Psparse, b, verbose = FALSE) 19.01142 31.26858 39.28202
## lsolve.sor(Psparse, b, verbose = FALSE) 16.36028 27.79556 30.34358
## median uq max neval
## 22.12720 22.95007 66.70662 10
## 17.45886 19.57789 63.03436 10
## 32.95994 34.44790 78.12849 10
## 31.61104 35.10524 38.86998 10
where in our case, supporting sparse matrices have shown much superior results. Note that the size has been set to be small since dense solvers are too slow to be manageably visible.