Suche…


Systemzeit

Die Systemzeit gibt die CPU-Zeit an, die zum Ausführen eines R-Ausdrucks erforderlich ist. Beispiel:

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

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

Sie können größere Codeteile mithilfe von geschweiften Klammern hinzufügen:

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

Oder verwenden Sie es zum Testen von Funktionen:

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 ()

Im einfachsten proc.time() gibt proc.time() die gesamte verstrichene CPU-Zeit in Sekunden für den aktuellen Prozess an. Wenn Sie es in der Konsole ausführen, erhalten Sie folgende Ausgabe:

proc.time()

#       user     system    elapsed 
#    284.507    120.397 515029.305 

Dies ist besonders nützlich für das Benchmarking bestimmter Codezeilen. Zum Beispiel:

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)

Dies ergibt die folgende Ausgabe:

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() ist ein Wrapper für proc.time() , der die abgelaufene Zeit für einen bestimmten Befehl / Ausdruck zurückgibt.

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

Beachten Sie, dass das zurückgegebene Objekt der Klasse proc.time etwas komplizierter ist, als es auf der Oberfläche erscheint:

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" ...

Linienprofilierung

Ein Paket für das Line-Profiling ist Lineprof, das von Hadley Wickham geschrieben und verwaltet wird. Hier eine auto.arima Demonstration, wie es mit auto.arima im Prognosepaket funktioniert:

library(lineprof)
library(forecast)

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

Dadurch erhalten Sie eine glänzende App, mit der Sie tiefer in jeden Funktionsaufruf einsteigen können. So können Sie mit Leichtigkeit sehen, was dazu führt, dass Ihr R-Code langsamer wird. Unten sehen Sie einen Screenshot der glänzenden App:

Geben Sie hier die Bildbeschreibung ein

Mikrobankmark

Mikrobankmarkierung ist nützlich, um die Zeit für ansonsten schnelle Verfahren abzuschätzen. Stellen Sie sich beispielsweise vor, wie viel Zeit benötigt wird, um Hallo Welt zu drucken.

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

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

Dies liegt daran, dass system.time im Wesentlichen eine Wrapper-Funktion für proc.time , die in Sekunden misst. Da der Druck "Hallo Welt" weniger als eine Sekunde dauert, scheint die Zeit weniger als eine Sekunde zu sein, dies ist jedoch nicht der Fall. Um dies zu sehen, können wir das Paket microbenchmark verwenden:

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

Nachdem wir print("hello world") 100 Mal ausgeführt haben, betrug die durchschnittliche Zeit tatsächlich 44 Mikrosekunden. (Beachten Sie, dass beim Ausführen dieses Codes "Hallo Welt" 100 Mal auf die Konsole gedruckt wird.)

Wir können dies mit einem gleichwertigen Verfahren, cat("hello world\n") , um zu sehen, ob es schneller ist als 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

In diesem Fall ist cat() fast doppelt so schnell wie print() .

Alternativ können zwei Verfahren innerhalb desselben microbenchmark Aufrufs verglichen werden:

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

Benchmarking mit Mikrobankmark

Sie können das microbenchmark Paket verwenden, um ein "präzises Timing der Ausdrucksauswertung unter einer Millisekunde" durchzuführen.

In diesem Beispiel vergleichen wir die Geschwindigkeiten von sechs äquivalenten data.table Ausdrücken zum Aktualisieren von Elementen in einer Gruppe basierend auf einer bestimmten Bedingung.

Genauer:

Eine data.table mit 3 Spalten: id , time und status . Für jede ID möchte ich den Datensatz mit der maximalen Zeit suchen. Wenn für diesen Datensatz der Status true ist, möchte ich ihn auf false setzen, wenn die Zeit> 7 ist

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

Die Ausgabe zeigt, dass expression_3 in diesem Test der schnellste ist.

Verweise

data.table - Spalten hinzufügen und ändern

data.table - spezielle Gruppierungssymbole in data.table



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow