R 与常规矩阵类相比,矩阵包中的提取速度非常慢
这是一个使用与常规R 与常规矩阵类相比,矩阵包中的提取速度非常慢,r,performance,matrix,sparse-matrix,R,Performance,Matrix,Sparse Matrix,这是一个使用与常规R类比较稀疏和密集的大型矩阵行提取的示例 对于密集矩阵,基类矩阵的速度几乎快395倍: library(Matrix) library(microbenchmark) ## row extraction in dense matrices D1<-matrix(rnorm(2000^2), 2000, 2000) D2<-Matrix(D1) > microbenchmark(D1[1,], D2[1,]) Unit: microseconds ex
R
类比较稀疏和密集的大型矩阵行提取的示例
对于密集矩阵,基类矩阵的速度几乎快395倍:
library(Matrix)
library(microbenchmark)
## row extraction in dense matrices
D1<-matrix(rnorm(2000^2), 2000, 2000)
D2<-Matrix(D1)
> microbenchmark(D1[1,], D2[1,])
Unit: microseconds
expr min lq mean median uq max neval
D1[1, ] 14.437 15.9205 31.72903 31.4835 46.907 75.101 100
D2[1, ] 5730.730 5744.0130 5905.11338 5777.3570 5851.083 7447.118 100
为什么会出现速度差异?有没有办法加快软件包中的提取速度?我不知道到底是什么问题,可能是S4调度(这可能是像这样的小调用中的一大块)。通过(1)切换到行主格式和(2)编写我自己的专用访问函数,我能够获得相当于矩阵
(这项工作非常简单,索引+访问连续内存块)的性能。我不知道你到底想做什么,也不知道你是否值得这么麻烦
树立榜样:
set.seed(101)
S1 <- matrix(1*(runif(2000^2)<0.1), 2000, 2000)
自定义访问器:
my_row_extract <- function(m,i=1) {
r <- numeric(ncol(m)) ## set up zero vector for results
## suggested by @OttToomet, handles empty rows
inds <- seq(from=m@p[i]+1,
to=m@p[i+1], length.out=max(0, m@p[i+1] - m@p[i]))
r[m@j[inds]+1] <- m@x[inds] ## set values
return(r)
}
基准:
benchmark(S1[1,], S2C[1,], S2R[1,], my_row_extract(S2R,1),
columns=c("test","elapsed","relative"))
## test elapsed relative
## 4 my_row_extract(S2R, 1) 0.015 1.154
## 1 S1[1, ] 0.013 1.000
## 2 S2C[1, ] 0.563 43.308
## 3 S2R[1, ] 4.113 316.385
专用提取器与基矩阵具有竞争性S2R
速度非常慢,即使对于行提取也是如此(令人惊讶);但是,?“dgRMatrix类”
确实说
注意:“矩阵”软件包中首选并更好地支持面向列的稀疏类,例如“dgCMatrix”
只有当行i不为空时,该函数才能正常工作。如果要处理空行,请使用类似于inds的方法
my_row_extract <- function(m,i=1) {
r <- numeric(ncol(m)) ## set up zero vector for results
## suggested by @OttToomet, handles empty rows
inds <- seq(from=m@p[i]+1,
to=m@p[i+1], length.out=max(0, m@p[i+1] - m@p[i]))
r[m@j[inds]+1] <- m@x[inds] ## set values
return(r)
}
all.equal(S2C[1,],S1[1,])
all.equal(S2C[1,],S2R[1,])
all.equal(my_row_extract(S2R,1),S2R[1,])
all.equal(my_row_extract(S2R,17),S2R[17,])
benchmark(S1[1,], S2C[1,], S2R[1,], my_row_extract(S2R,1),
columns=c("test","elapsed","relative"))
## test elapsed relative
## 4 my_row_extract(S2R, 1) 0.015 1.154
## 1 S1[1, ] 0.013 1.000
## 2 S2C[1, ] 0.563 43.308
## 3 S2R[1, ] 4.113 316.385