あなたは長さゼロのリストを割り当て、その後、代わりに各反復
listKseq <- vector(mode = "list", length = 0)
...
listKseq <- c(listKseq, ki)
でそれを育てる「コピー・アンド・APPENDの戦略、「事前に割り当てと塗りつぶしを持っています'
listKseq <- vector(mode = "list", length = N)
...
listKseq[[k]] = ki
『コピー・アンド・APPEND』戦略は、既に計算されたすべてのデータのコピーを作成し、ループを通るたびに、それは、として多項式の複雑さ(スケールを有しています、約N^2
)。事前割り振りと塗りつぶしはコピーを生成せず、N
で直線的に拡大します。ここ
は、元の変性実装
f0 <- function(N) {
gamma1 <- 2.2
C1 <- zeta(x = gamma1)
C1inverse <- 1/C1
listKseq <- vector(mode = "list", length = 0)
for(k in 1:N) {
ki <- N * C1inverse * k^(-gamma1)
listKseq <- c(listKseq, ki)
}
listKseq
}
f1 <- function(N) {
gamma1 <- 2.2
C1 <- zeta(x = gamma1)
C1inverse <- 1/C1
listKseq <- vector(mode = "list", length = N)
for(k in 1:N) {
ki <- N * C1inverse * k^(-gamma1)
listKseq[[k]] <- ki
}
listKseq
}
それらは
> identical(f0(1000), f1(1000))
[1] TRUE
とf1()
において
> library(microbenchmark)
> microbenchmark(f0(1000), f0(10000), f1(1000), f1(10000), times=10)
Unit: milliseconds
expr min lq mean median uq max
f0(1000) 9.017734 9.128453 9.779840 9.242001 9.275092 14.975256
f0(10000) 954.733153 965.318717 1002.789735 969.329023 1002.291013 1125.090369
f1(1000) 2.332049 2.417364 2.462379 2.461930 2.488568 2.583112
f1(10000) 22.220757 22.393636 22.725043 22.503726 22.797767 24.376800
neval cld
10 a
10 b
10 a
10 a
に記載されているように、それらが拡張するのと同じ結果を返すデモンストレーション、負担ですコードを書く人にあらかじめ割り当てて記入してください。 、あなたの計算が...「ベクトル化」の代わりのループ
f2 <- function(N) {
gamma1 <- 2.2
C1 <- zeta(x = gamma1)
C1inverse <- 1/C1
as.list(N * C1inverse * seq_len(N)^(-gamma1))
}
のように書くことができ
f1a <- function(N) {
gamma1 <- 2.2
C1 <- zeta(x = gamma1)
C1inverse <- 1/C1
lapply(seq_len(N), function(k) N * C1inverse * k^(gamma1))
}
さらに、より表現と自由なコンパクト、かつ堅牢なコードのために、この動作を取得するにはlapply()
を使用し、シンプルなベクトルが
f3 <- function(N) {
gamma1 <- 2.2
C1 <- zeta(x = gamma1)
C1inverse <- 1/C1
N * C1inverse * seq_len(N)^(-gamma1)
}
アイデンティティと時間が
ているんだろうというときには、リストの長-1の要素を戻すことは意味がありません
> identical(unlist(f1(1000)), f3(1000))
[1] TRUE
> microbenchmark(f1(10000), f2(10000), f3(10000), times=10)
Unit: microseconds
expr min lq mean median uq max neval
f1(10000) 22330.886 22482.578 24223.9281 22939.443 24100.424 30414.666 10
f2(10000) 1196.715 1217.937 1256.7939 1242.236 1256.622 1401.922 10
f3(10000) 887.824 909.951 981.8528 979.900 996.471 1201.596 10
cld
b
a
a
これらの改良がどのように役立つかを知るにはきれいです。アルゴリズムのスケーリングは、大規模なデータ、ベクトル化の使用、そして最終的には適切な表現にとって最も重要です。ある時点では、コードが「十分に良い」ものであるため、考えを止めるだろう。
コピーアンドアペンドは非常に悪い戦略なので、長さが不明確でサイズがres = vector("list", 1e7); ...; length(res) = actual_length
になるように過剰に割り当ててトリミングしたり、大きなチャンクで割り当ててコピー&何回か。
例では、関数呼び出しzeta()を使用しました。これはベースRパッケージにはありません。重要である場合(例えばスカラー以外の結果を返すなど)、どこから来るのかを指定する必要があります。単純な番号を返すだけであれば、それを編集する必要があります。 –
ええ、私のgoogleベースの推測はライブラリ(VGAM)です – Frank