为什么分配矩阵的行/列要比填充相同大小的矢量慢得多?
N <- 1e8
u <- numeric(N)
system.time(u <- 1:N)
##user system elapsed
##0.091 0.100 0.191
u <- matrix(nrow=2,ncol=N)
system.time(u[1,] <- 1:N)
##user system elapsed
##2.772 0.436 3.212
我主要担心的是数组,但我想矩阵的答案也会解释数组。
N <- 1e3
uu <- matrix(N,N)
system.time({uu <- 1:(N*N)})
##user system elapsed
##0.068 0.120 0.188
uu <- array(dim=c(2,N,N))
system.time({uu[1,,] <- 1:(N*N)})
##user system elapsed
##4.409 0.241 4.657
(我无法判断分配给大型预分配向量的元素是否比分配给变量慢,因为前者对于我的系统能够分配的任何向量总是花费0倍。)
答案 0 :(得分:2)
因为您填写的行不是列。您会获得更多缓存未命中,以及地址算术开销(定位每列的基址)。
在R中,矩阵或一般数组本质上是一个长向量;维度只是一个属性。最快的索引是最右边的索引,因此当您通过列扫描矩阵时,元素是连续的,或者按最后一个边距扫描数组。这意味着,在具有64字节L1高速缓存行大小的典型机器上,可以容纳8个双精度数字,每次扫描8个元素就有1个高速缓存未命中。但是,如果您逐行访问两行矩阵,则每4个元素将获得1个缓存未命中。
另一个问题,给你一个不公平的比较,就是你要将覆盖与赋值进行比较,而不是覆盖覆盖。使用u[] <- 1:N
将强制覆盖预分配的向量u
。
考虑以下基准测试:
library(microbenchmark)
n <- 10000
u <- 1:n
m1 <- matrix(0, n, 2)
m2 <- matrix(0, 2, n)
x <- numeric(n)
microbenchmark (m1[,1] <- u, m2[1,] <- u, x[] <- u)