为什么在R中应用的速度不比%*%慢?

时间:2013-03-19 11:24:37

标签: r loops optimization sum

以下是带输出的示例代码:

set.seed(234)
a <- matrix(rnorm(100000), 10000,100)
dim(a)

fo1 <- function() apply(a, 1, sum)
fo2 <- function() a %*% rep(1, 100)
fo3 <- function() {
    n <- nrow(a)
    x <- numeric(n)
    for(i in seq_len(n))  x[i] <- sum(a[i, ])
    }
fo4 <- function() rowSums(a)

# install.packages("microbenchmark")
require(microbenchmark)

microbenchmark(fo1 , fo2, fo3, fo4 ,times = 100000)
# expr min lq median uq    max neval
#  fo1  81 90     91 96 188969 1e+05
#  fo2  75 87     90 94 241332 1e+05
#  fo3  75 84     87 91 271085 1e+05
#  fo4  72 88     91 97 39447 1e+05

我认为apply和循环应该比矢量化版本或专用的rowSums函数慢 - 但它们似乎都给出了非常相似的结果(除了最大值)。

有人能说明为何会出现这种情况吗?

1 个答案:

答案 0 :(得分:3)

就像@Martin所说,你没有在microbenchmark中调用这些函数。此外,函数fo3不会返回任何内容:

fo3 <- function() {
    n <- nrow(a)
    x <- numeric(n)
    for(i in seq_len(n))  x[i] <- sum(a[i, ])
    x #you missed this
}

并且fo2返回矩阵,而其他函数返回向量。所以让我们使用

fo2 <- function() c(a %*% rep(1, 100))

以下是正确的结果:

microbenchmark(fo1() , fo2(), fo3(), fo4() ,times = 100)
Unit: milliseconds
  expr       min        lq    median        uq       max neval
 fo1() 33.437565 37.859724 39.961079 41.409828 85.950181   100
 fo2()  1.756187  1.820632  1.861232  1.899416  2.138938   100
 fo3() 35.356449 37.069169 37.713325 39.624361 51.001235   100
 fo4()  2.467656  2.529235  2.561986  2.616621  2.884215   100

您会发现矩阵向量乘法最快,但与rowSums的差异非常小(调用内部.rowSums而不会影响结果)。 applyfor循环方法之间的差异也很小,因为apply只是伪装的循环。

请注意

> identical(fo1(),fo2())
[1] FALSE
> identical(fo1(),fo3())
[1] TRUE
> identical(fo1(),fo4())
[1] TRUE
> all.equal(fo1(),fo2())
[1] TRUE

矩阵乘法版本的结果与其他版本略有不同。