【问题标题】:why is filling a row of a matrix much slower than filling vector of the same size为什么填充矩阵的一行比填充相同大小的向量慢得多
【发布时间】:2017-08-25 05:26:31
【问题描述】:

为什么分配给矩阵的行/列比填充相同大小的向量要慢得多?

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 时间。)

【问题讨论】:

  • 我看到你通过速度测试完全正确,但你能更详细地解释一下吗?你是说一列将连续存储以便缓存位置,而填充一行需要每 N 个元素跳转一次,所以重新计算位置?
  • 但我也使用了数字作为向量。应该有相同数量的 int->numeric 转换,对吧?

标签: arrays r performance matrix


【解决方案1】:

因为您填写的是一行而不是一列。你会得到更多的缓存未命中,以及地址算术开销(定位每列的基地址)。

在R中,矩阵或一般数组本质上是一个长向量;维度只是一个属性。最快的索引是最右边的索引,因此当您按列扫描矩阵或按最后一个边距扫描数组时,元素是连续的。这意味着,在具有 64 字节 L1 高速缓存行大小的典型机器上,可以容纳 8 个双精度数字,每次扫描 8 个元素有 1 次高速缓存未命中。但是,例如,如果您逐行访问包含两行的矩阵,则每 4 个元素会出现 1 次缓存未命中。

另一个问题,给你一个不公平的比较,你是在比较覆盖和赋值,而不是覆盖和覆盖。使用u[] &lt;- 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)

【讨论】:

    猜你喜欢
    • 2016-10-07
    • 2014-11-21
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    相关资源
    最近更新 更多