-1

出力付きのサンプルコードは次のとおりです。

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とloopsは、ベクトル化されたバージョンや専用のrowSums関数よりも遅いはずだと思いましたが、それらはすべて非常によく似た結果をもたらすようです(最大値を除く)。

なぜこれが当てはまるのか誰かが提案できますか?

4

1 に答える 1

3

@Martinが指摘したように、マイクロベンチマークで関数を呼び出していません。また、関数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も結果には影響しません)。applyとループのアプローチの違いforも小さく、apply変装したループも同様です。

ご了承ください

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

行列乗算バージョンでは、他のバージョンとはわずかに異なる結果が得られます。

于 2013-03-19T11:37:50.747 に答える