サーチ…


システム時刻

システム時刻は、R式を実行するために必要なCPU時間を示します。たとえば、次のようになります。

system.time(print("hello world"))

# [1] "hello world"
#    user  system elapsed 
#       0       0       0 

中括弧を使用して、より大きなコードを追加することができます。

system.time({
    library(numbers)
    Primes(1,10^5)
})

または、関数をテストするために使用します。

fibb <- function (n) {   
    if (n < 3) {
        return(c(0,1)[n])
    } else {
        return(fibb(n - 2) + fibb(n -1))
    }
}

system.time(fibb(30))

proc.time()

最も簡単な場合、 proc.time()は、現在のプロセスの合計CPU時間を秒単位でproc.time()ます。コンソールで実行すると、次のような出力が得られます。

proc.time()

#       user     system    elapsed 
#    284.507    120.397 515029.305 

これは、特定のコード行をベンチマークする場合に特に便利です。例えば:

t1 <- proc.time()
fibb <- function (n) {
    if (n < 3) {
        return(c(0,1)[n])
    } else {
        return(fibb(n - 2) + fibb(n -1))
    }
}
print("Time one")
print(proc.time() - t1)

t2 <- proc.time()
fibb(30)

print("Time two")
print(proc.time() - t2)

これにより、次の出力が得られます。

source('~/.active-rstudio-document')

# [1] "Time one"
#    user  system elapsed 
#       0       0       0 

# [1] "Time two"
#    user  system elapsed 
#   1.534   0.012   1.572 

system.time()は、特定のコマンド/式の経過時間を返すproc.time()ラッパーです。

print(t1 <- system.time(replicate(1000,12^2)))
##  user  system elapsed 
## 0.000   0.000   0.002 

クラスproc.time返されるオブジェクトは、サーフェスに表示されるよりもやや複雑です。

str(t1)
## Class 'proc_time'  Named num [1:5] 0 0 0.002 0 0
##  ..- attr(*, "names")= chr [1:5] "user.self" "sys.self" "elapsed" "user.child" ...

ラインプロファイリング

ラインプロファイリングのための1つのパッケージは、Hadley Wickhamによって書かれ維持されているlineprofです。予測パッケージのauto.arimaでどのように動作するかを簡単に説明します。

library(lineprof)
library(forecast)

l <- lineprof(auto.arima(AirPassengers))
shine(l)

これは光るアプリを提供します。これにより、すべての関数呼び出しを深く掘り下げることができます。これにより、Rコードが遅くなっている原因を簡単に確認することができます。以下のような光沢のあるアプリのスクリーンショットがあります:

ここに画像の説明を入力

マイクロベンチマーク

Microbenchmarkは、その他の高速手順では時間の見積もりに役立ちます。たとえば、こんにちは世界を印刷するのにかかる時間を見積もることを検討してください。

system.time(print("hello world"))

# [1] "hello world"
#    user  system elapsed 
#       0       0       0 

これは、 system.timeが本質的にproc.timeラッパー関数でproc.time 、秒単位で測定されるためproc.time 。 "hello world"の印刷には1秒もかかりませんので、撮影時間は1秒未満ですが、これは当てはまりません。これを見るために、パッケージのマイクロベンチマークを使用することができます:

library(microbenchmark)
microbenchmark(print("hello world"))
 
# Unit: microseconds
#                 expr    min     lq     mean  median     uq     max neval
# print("hello world") 26.336 29.984 44.11637 44.6835 45.415 158.824   100

ここでprint("hello world") 100回実行した後、平均して44マイクロ秒であった。 (このコードを実行すると "hello world"がコンソールに100回印刷されることに注意してください)。

これを同等の手続きcat("hello world\n")と比較して、 print("hello world")より高速かどうかを調べることができprint("hello world")

microbenchmark(cat("hello world\n"))

# Unit: microseconds
#                  expr    min      lq     mean median     uq     max neval
# cat("hello world\\n") 14.093 17.6975 23.73829 19.319 20.996 119.382   100

この場合、 cat()print()ほぼ2倍の速さです。

あるいは、同じmicrobenchmarkコール内の2つの手順を比較することもできます。

microbenchmark(print("hello world"), cat("hello world\n"))
# Unit: microseconds
# expr                    min     lq     mean  median     uq     max neval
# print("hello world") 29.122 31.654 39.64255 34.5275 38.852 192.779   100
# cat("hello world\\n")  9.381 12.356 13.83820 12.9930 13.715  52.564   100

マイクロベンチマークを使用したベンチマーク

microbenchmarkパッケージを使用して、「ミリ秒以下の正確な式評価のタイミング」を実行できます。

この例では、特定の条件に基づいて、グループ内の要素を更新するための6つの同等のdata.table式の速度を比較しています。

すなわち:

idtimestatus 3列のdata.table 。各idに対して、最大時間のレコードを検索したい - ステータスがtrueならそのレコードのために時間が7より大きい場合はfalseに設定したい

library(microbenchmark)
library(data.table)

set.seed(20160723)
dt <- data.table(id = c(rep(seq(1:10000), each = 10)),
                time = c(rep(seq(1:10000), 10)),
                status = c(sample(c(TRUE, FALSE), 10000*10, replace = TRUE)))
setkey(dt, id, time)  ## create copies of the data so the 'updates-by-reference' don't affect other expressions
dt1 <- copy(dt)
dt2 <- copy(dt)
dt3 <- copy(dt)
dt4 <- copy(dt)
dt5 <- copy(dt)
dt6 <- copy(dt)

microbenchmark(
  
  expression_1 = {
    dt1[ dt1[order(time), .I[.N], by = id]$V1, status := status * time < 7 ] 
    },
  
  expression_2 = {
    dt2[,status := c(.SD[-.N, status], .SD[.N, status * time > 7]), by = id]
    },
  
  expression_3 = {
    dt3[dt3[,.N, by = id][,cumsum(N)], status := status * time > 7]
    },
  
  expression_4 = { 
    y <- dt4[,.SD[.N],by=id]
    dt4[y, status := status & time > 7]
  },
  
  expression_5 = {
    y <- dt5[, .SD[.N, .(time, status)], by = id][time > 7 & status]
    dt5[y, status := FALSE]
  },
  
  expression_6 = {
    dt6[ dt6[, .I == .I[which.max(time)], by = id]$V1 & time > 7, status := FALSE]
    },
  
  times = 10L ## specify the number of times each expression is evaluated
)

# Unit: milliseconds
#         expr         min          lq        mean      median         uq          max neval
# expression_1   11.646149   13.201670   16.808399   15.643384   18.78640    26.321346    10
# expression_2 8051.898126 8777.016935 9238.323459 8979.553856 9281.93377 12610.869058    10
# expression_3    3.208773    3.385841    4.207903    4.089515    4.70146     5.654702    10
# expression_4   15.758441   16.247833   20.677038   19.028982   21.04170    36.373153    10
# expression_5 7552.970295 8051.080753 8702.064620 8861.608629 9308.62842  9722.234921    10
# expression_6   18.403105   18.812785   22.427984   21.966764   24.66930    28.607064    10

出力は、このテストではexpression_3が最も速いことを示しています。

参考文献

data.table - 列の追加と変更

data.table - data.tableの特殊なグループ化シンボル



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow