Data.table: beitreten Betrieb fast 2 mal langsamer

Erstellt am 2. Okt. 2019  ·  29Kommentare  ·  Quelle: Rdatatable/data.table

Hallo, ich habe getestet
data.table_1.10.4-3 + R-Version 3.4.0 (2017-04-21)
vs
data.table_1.12.2 + R-Version 3.6.1 (2019-07-05)

und haben festgestellt, dass der Join-Vorgang in der neuen Version data.table (R?) fast 2-mal langsamer ist.
Ich denke, hängt hauptsächlich von der Version von data.table ab

rm(list=ls())

library(data.table)
library(tictoc)


aa = data.table(a = seq(1,100), b = rep(0, 100))
bb = data.table(a = seq(1,100), b = rep(1, 100))

#aa[,  a1 := as.character(a)]
#bb[,  a1 := as.character(a)]

setindex(aa, a)
setindex(bb, a)

tic()
for(i in c(1:1000)) {
 # aa[bb, b := i.b, on=.(a, a1)] # test1
  aa[bb, b := i.b, on=.(a)] # test2
}
toc()

# test1
# 3.6.1: 5.5 sec with index
# 3.6.1: 6.87 sec without index
# 3.4.0: 3.02 sec (no index)

# test2
# 3.6.1: 3.82 sec with index
# 3.6.1: 4.44 sec without index
# 3.4.0: 2.48 sec (no index)
High joins performance regression

Alle 29 Kommentare

Habe folgendes ausgeführt:

# run_join_time.sh
echo 'hash,time' > 'join_timings.csv'

for HASH in $(git rev-list --ancestry-path 1.10.0..1.12.4 | awk 'NR == 1 || NR % 10 == 0');
do git checkout $HASH && R CMD INSTALL . && Rscript time_join.R $HASH;
done
# time_join.R
library(data.table)
library(microbenchmark)

hash = commandArgs(trailingOnly = TRUE)

aa = data.table(a = seq(1,100), b = rep(0, 100))
bb = data.table(a = seq(1,100), b = rep(1, 100))

fwrite(data.table(
  hash = hash,
  time = microbenchmark(times = 1000L, aa[bb, b := i.b, on=.(a)])$time
), 'join_timings.csv', append = TRUE)

Gehen Sie dann wie folgt vor, um dieses Diagramm zu erstellen

Screenshot 2019-10-03 at 6 59 11 PM

library(data.table)
times = fread('join_timings.csv')

times[ , date := as.POSIXct(system(sprintf("git show --no-patch --no-notes --pretty='%%cd' %s", .BY$hash), intern = TRUE), by = hash]
times[ , date := as.POSIXct(date, format = '%a %b %d %T %Y %z', tz = 'UTC')]
times[ , date := as.IDate(date)]
setorder(times, date)

tags = system('
for TAG in $(git tag);
  do git show --no-patch --no-notes --pretty="$TAG\t%cd" $TAG;
done
', intern = TRUE)

tags = setDT(tstrsplit(tags, '\t'))
setnames(tags, c('tag', 'date'))
tags[ , date := as.POSIXct(date, format = '%a %b %d %T %Y %z', tz = 'UTC')]
tags[ , date := as.IDate(date)]

times[ , {
  par(mar = c(7.1, 4.1, 2.1, 2.1))
  y = boxplot(I(time/1e6) ~ date, log = 'y', notch = TRUE, pch = '.',
              las = 2L, xlab = '', ylab = 'Execution time (ms)', cex.axis = .8)
  x = unique(date)
  idx = findInterval(tags$date, x)
  abline(v = idx[idx>0L], lty = 2L, col = 'red')
  text(idx[idx>0L], .7*10^(par('usr')[4L]), tags$tag[idx>0L], 
       col = 'red', srt = 90)
  NULL
}]


Nach dem Start wurde mir klar, dass ich dies durch die Verwendung ein wenig rationalisieren konnte

echo 'hash,time,date' > 'join_timings.csv'

for HASH in $(git rev-list --ancestry-path 1.10.0..1.12.4 | awk 'NR == 1 || NR % 10 == 0');
do git checkout $HASH && R CMD INSTALL . --preclean && Rscript time_join.R $HASH $(git show --no-patch --no-notes --pretty='%cd' $HASH);
done
library(data.table)
library(microbenchmark)

args = commandArgs(trailingOnly = TRUE)
hash = args[1L]
date = as.POSIXct(args[2L], format = '%a %b %d %T %Y %z', tz = 'UTC'))

aa = data.table(a = seq(1,100), b = rep(0, 100))
bb = data.table(a = seq(1,100), b = rep(1, 100))

fwrite(data.table(
  hash = hash,
  date = date,
  time = microbenchmark(times = 1000L, aa[bb, b := i.b, on=.(a)])$time
), 'join_timings.csv', append = TRUE)

um die Commit-Zeit direkt zum Benchmark hinzuzufügen

join_timings.txt

Hallo MichaelChirico, ich habe zweimal gelesen
aber was genau bedeutet die Zeitleiste von 2016 bis 2019? Ist es eine Version von Datatable?

nicht nur Versionen, sondern spezifische Commits. Lassen Sie mich versuchen, eine Abgrenzung der Versionen hinzuzufügen, eine gute Idee, die ich vergessen habe, hinzuzufügen

@MichaelChirico dein Graph sieht super cool aus, was fehlte, war eine Interpretation davon :) Wenn ich schätze, würde ich sagen, dass der neue parallele Forder für eine Eingabe der Länge 100 langsamer ist als zuvor. Was meiner Meinung nach in Ordnung ist, denn das sind immer noch Mikrosekunden. Es lohnt sich natürlich, den Overhead zu reduzieren, aber die Priorität sollte eine Reduzierung der Ressourcen in den häufigsten Anwendungsszenarien sein. 10000 Schleifen auf einem Input der Länge 100 gehört definitiv nicht dazu.

das war auch meine Vermutung nach einem Blick in die 1.12.0 NEWS. werde versuchen, Single-Threading erneut auszuführen.

@jangorecki , wenn Sie die einfache Mathematik machen, sind es Tausende von Mikrosekunden, dh Millisekunden
Die Inspiration für diesen Test war mein aktuelles Projekt, bei dem ich 7-8 Einmaleins-Reihen mit 40 000 Zeilen verbinde
Vorher dauert es 18 Sekunden, danach 40 Sekunden
Mein Test beinhaltet auch die Zeichentaste
Ich habe 3.6+1.12 installiert und dann auf 3.4+1.10 zurückgesetzt
Ich denke, das ist keine normale Situation, deshalb ist dieses Problem hier

Ja, die Grafik ist wirklich großartig; wir sollten mehr davon machen und es automatisieren.

Aber der ursprüngliche Bericht vergleicht R 3,4 mit R 3,6, das R 3,5 in der Mitte hat. Wir wissen, dass R 3.5 data.table über ALTREPs Änderung von REAL(), INTEGER() von Makros zu (etwas schwereren) Funktionen beeinflusst hat.

@vk111 Können Sie bitte Ihre Tests mit v1.12.4 jetzt auf CRAN wiederholen. Etwas besser? Wir haben die R-API außerhalb der Schleifen geführt, um mit R 3.5+ fertig zu werden. Als nächsten Schritt wäre es toll zu wissen, wie Sie v1.12.4 finden. Können Sie auch weitere Informationen zu Ihrer Maschine hinzufügen? B. Betriebssystem, RAM und Anzahl der CPUs.

@matt , geht

Hallo @mattdowle ,

Ich habe auf 1.12.4 (+R 3.6.1) aktualisiert - im Grunde gibt es die gleichen Zahlen für Unit-Test und meine Funktion
Ich werde hier nur Verknüpfungen mit Zeichen ohne Indizierung betrachten - als Benchmark
Unit-Test (wie im ersten Beitrag erwähnt)
3.6.1: 6,87 Sek. ohne Index
3.4.0: 3,02 Sek. (kein Index)

Meine Funktion aus dem Projekt bleibt gleich: 20 vs. 40 Sekunden
Es besteht nur aus ~14 dt Joins
zwei Tabellen 30 000 Zeilen (dt1) und 366 000 Zeilen (dt2)
Jeweils 15 Spalten
Der Schlüssel besteht aus 2 Zeichen und 1 Ziffer
und während des Joins 7 Felder (von dt1 bis dt2) zugewiesen

mein PC:
Gewinnen Sie 10 64-Bit
AMD A8 2,2 GHz
8 GB Arbeitsspeicher

cmd: wmic cpu get NumberOfCores, NumberOfLogicalProcessors/ Format:List
NumberOfCores=4
NumberOfLogicalProcessors=4

Vielen Dank für Ihre Analyse

Hallo @mattdowle , also denkst du darüber nach?

Laut einem git bisect , den ich gerade erneut ausgeführt habe, ist dieser Commit „schuldig“ für die Verlangsamung, hoffentlich kann das Matt dabei helfen, die Wurzel zu finden. Dass es mit forder zusammenhängt, macht mich relativ zuversichtlich, dass wir es richtig festgelegt haben.

https://github.com/Rdatatable/data.table/commit/e59ba149f21bb35098ed0b527505d5ed6c5cb0db

Etwas präziser:

# run_join_time.sh
R CMD INSTALL . && Rscript time_join.R
# time_join.R
library(data.table)
library(microbenchmark)

aa = data.table(a = seq(1,100), b = rep(0, 100))
bb = data.table(a = seq(1,100), b = rep(1, 100))

summary(microbenchmark(times = 1000L, aa[bb, b := i.b, on=.(a)])$time/1e6)

Mit diesen beiden Skripten von master/HEAD :

git checkout 1.12.0
git bisect start
git bisect bad
git bisect good 1.11.8

Führen Sie dann bei jeder Iteration sh run_join_time.sh aus und überprüfen Sie das Ergebnis. Die bad -Commits dauerten ungefähr 0,9 Sekunden pro Iteration auf meiner Maschine, good -Commits etwa 0,7.

Hallo Michael, danke, aber besonders die Leistung ist dramatisch gesunken
für die Zeichentaste habe ich den Unit-Test im allerersten Post bereitgestellt
Wie auch immer, ich denke, wir müssen auf die Bestätigung von Matt warten, ob es behoben ist
neue Version oder nicht

Am Donnerstag, 26. Dezember 2019 um 15:02 Uhr, Michael Chirico [email protected]
schrieb:

Laut einem Git bisect, den ich gerade erneut ausgeführt habe, ist dieser Commit "schuldig" für die
verlangsamen, hoffentlich kann das Matt helfen, die Wurzel zu finden. Das ist es
im Zusammenhang mit forder macht mich relativ zuversichtlich, dass wir es festgenagelt haben
korrekt.

e59ba14
https://github.com/Rdatatable/data.table/commit/e59ba149f21bb35098ed0b527505d5ed6c5cb0db

Etwas präziser:

run_join_time.sh

R CMD-INSTALLATION . && Rscript time_join.R

time_join.R

Bibliothek (data.table)
Bibliothek (Mikrobenchmark)

aa = data.table(a = seq(1.100), b = rep(0, 100))
bb = data.table(a = seq(1.100), b = rep(1, 100))

summary(microbenchmark(times = 1000L, aa[bb, b := ib, on=.(a)])$time/1e6)

Mit diesen beiden Skripten von master/HEAD:

git checkout 1.12.0
git halbieren start
git halbieren schlecht
git bisect gut 1.11.8

Führen Sie dann bei jeder Iteration sh run_join_time.sh aus und überprüfen Sie das Ergebnis. Der
Schlechte Commits dauerten auf meinem Rechner ungefähr 0,9 Sekunden pro Iteration,
gute Commits über .7.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Rdatatable/data.table/issues/3928?email_source=notifications&email_token=ABRM7MJQITNUZDNYV7NTIX3Q2S2ORA5CNFSM4I4ZPREKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHVTR4Q#issuecomment-56696 ,
oder abbestellen
https://github.com/notifications/unsubscribe-auth/ABRM7MOTZRFFM2QKVFUHT6LQ2S2ORANCNFSM4I4ZPREA
.

>

Mit freundlichen Grüßen,
Wassili Kusnezow

@vk111 Wenn dieses Problem nicht geschlossen ist, können Sie davon ausgehen, dass das Problem noch nicht behoben ist. Wann immer wir etwas beheben, schließen wir das zugehörige Problem.

@vk111 Sie können möglicherweise mit einigen kleineren Optimierungen Abhilfe schaffen, indem Sie setkey anstelle von setindex verwenden. Dies verkürzt Ihren Test auf meinem Computer um mehr als die Hälfte:

aa = data.table(a = seq(1,100), b = rep(0, 100))
bb = data.table(a = seq(1,100), b = rep(1, 100))

aa[,  a1 := as.character(a)]
bb[,  a1 := as.character(a)]

tic()
for(i in c(1:1000)) {
  aa[bb, b := i.b, on=.(a, a1)] # test1 without key
}
toc()
## 4 sec elapsed

tic()
setkey(aa, a, a1)
setkey(bb, a, a1)

for(i in c(1:1000)) {
  aa[bb, b := i.b] # test2 without key
}
toc()
## 1.46 sec elapsed

image

library(microbenchmark)
library(data.table)

aa = data.table(a = seq(1,100), b = rep(0, 100))
bb = data.table(a = seq(1,100), b = rep(1, 100))

aa[,  a1 := as.character(a)]
bb[,  a1 := as.character(a)]

aa_nokey = copy(aa)
bb_nokey = copy(bb)

tic()
aa_int_key = setkey(copy(aa), a)
bb_int_key = setkey(copy(bb), a)
toc()

tic()
aa_int_char = setkey(copy(aa), a, a1)
bb_int_char = setkey(copy(bb), a, a1)
toc()
int_nokey = function(dt1, dt2){
  dt1[dt2, b := i.b, on=.(a)]
}

int_key = function(dt1, dt2){
  dt1[dt2, b := i.b]
}

int_char_nokey = function(dt1, dt2){
  dt1[dt2, b := i.b, on=.(a, a1)]
}

int_char_key = function(dt1, dt2){
  dt1[dt2, b := i.b]
}

int_char_key_on = function(dt1, dt2){
  dt1[dt2, b := i.b, on=.(a, a1)]
}

boxplot(
  microbenchmark(
    a_no_key = int_nokey(aa, bb),
    a_key = int_key(aa_int_key, bb_int_key),
    a_a1_no_key = int_char_nokey(aa, bb),
    a_a1_key = int_char_key(aa_int_char, bb_int_char),
    a_a1_key_on = int_char_key_on(aa_int_char, bb_int_char)
  )
)

Hallo Cole, ja, ich kenne setkey - ich habe oben die kurze Beschreibung angegeben
meines Projekts und es gibt keinen Zweck von 1000 Joins - es sind ungefähr 10-20
verbindet und die Sache ist, dass meine Zeichenfolgen sehr dynamisch sind und ich
Sie müssen jedes Mal einen Setkey machen, bevor Sie beitreten, wie 20 Mal Setkey und 20
mal hinzukommt und somit ist der Zeitgewinn weniger als 2 mal
Ich lebe eine Weile mit 3.4.0 als allgemeine Problemumgehung für diese Situation
und wahrscheinlich ist es keine große Sache, es in einer neuen Version zu beheben, besonders wenn
Es wurde ein schuldiges Commit gefunden
Übrigens, wenn wir Äpfel mit Äpfeln vergleichen, denke ich, dass es 3,4 (1,10) sein wird
immer noch schneller als 3.6 (1.12), wenn ich den gleichen Unit-Test mit dem Setkey for verwende
beide Versionen
Schöne Ferien

Am Sonntag, 29. Dezember 2019, 14:48 Uhr schrieb Cole Miller, [email protected] :

@vk111 https://github.com/vk111 können Sie möglicherweise mit einigen abmildern
kleinere Änderungen mit setkey anstelle von setindex. Dies verkürzt Ihren Test um
mehr als die Hälfte auf meinem Computer:

aa = data.table(a = seq(1.100), b = rep(0, 100))
bb = data.table(a = seq(1.100), b = rep(1, 100))

aa[, a1 := als.Zeichen(a)]
bb[, a1 := als.Zeichen(a)]

tick()
for(i in c(1:1000)) {
aa[bb, b := ib, on=.(a, a1)] # test1 ohne Schlüssel
}
toc()

4 Sekunden verstrichen

tick()
setkey(aa, a, a1)
setkey(bb, a, a1)

for(i in c(1:1000)) {
aa[bb, b := ib] # test2 ohne Schlüssel
}
toc()

1,46 Sekunden sind vergangen

[Bild: Bild]
https://user-images.githubusercontent.com/57992489/71557665-126d7880-2a17-11ea-8664-21a10deb47ca.png

Bibliothek (Mikrobenchmark)
Bibliothek (data.table)

aa = data.table(a = seq(1.100), b = rep(0, 100))
bb = data.table(a = seq(1.100), b = rep(1, 100))

aa[, a1 := als.Zeichen(a)]
bb[, a1 := als.Zeichen(a)]

aa_nokey = Kopie (aa)
bb_nokey = kopieren (bb)

tick()
aa_int_key = setkey(copy(aa), a)
bb_int_key = setkey(copy(bb), a)
toc()

tick()
aa_int_char = setkey(copy(aa), a, a1)
bb_int_char = setkey(copy(bb), a, a1)
toc()
int_nokey = function(dt1, dt2){
dt1[dt2, b := ib, on=.(a)]
}

int_key = funktion(dt1, dt2){
dt1[dt2, b := ib]
}

int_char_nokey = Funktion (dt1, dt2) {
dt1[dt2, b := ib, on=.(a, a1)]
}

int_char_key = Funktion (dt1, dt2) {
dt1[dt2, b := ib]
}

int_char_key_on = Funktion (dt1, dt2) {
dt1[dt2, b := ib, on=.(a, a1)]
}

Box-Plot(
Mikrobenchmark (
a_no_key = int_nokey(aa, bb),
a_key = int_key(aa_int_key, bb_int_key),
a_a1_no_key = int_char_nokey(aa, bb),
a_a1_key = int_char_key(aa_int_char, bb_int_char),
a_a1_key_on = int_char_key_on(aa_int_char, bb_int_char)
)
)


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Rdatatable/data.table/issues/3928?email_source=notifications&email_token=ABRM7MPU64YBK7UNT3O3OYDQ3CTBRA5CNFSM4I4ZPREKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHY73VA#issuecomment-284,950
oder abbestellen
https://github.com/notifications/unsubscribe-auth/ABRM7MKSP6LCUJD2HOAG7D3Q3CTBRANCNFSM4I4ZPREA
.

Es gibt eine ausstehende PR Nr. 4370, die damit zusammenhängt. Es kann mit weniger Overhead verbinden, als [ normalerweise auferlegt. Es reduziert das Timing Ihres Beispiels um den Faktor 2. Je größer die Daten, desto kleiner die Verbesserung, aber je mehr Iterationen, desto besser die Verbesserung. Beachten Sie, dass es keine Möglichkeit gibt, die Spalte während des Joins zu aktualisieren. Grundsätzlich müssen Sie während des Joins Spalten hinzufügen und dann etwas wie fcoalesce verwenden, aber das sollte performant sein.
Es sollte etwas mehr Geschwindigkeit bekommen, sobald #4386 ebenfalls zusammengeführt wird.

library(data.table)
aa = data.table(a = seq(1,100), b = rep(0, 100))
bb = data.table(a = seq(1,100), b = rep(1, 100))
setindex(aa, a)
setindex(bb, a)
p = proc.time()[[3L]]
for (i in c(1:1000)) {
  aa[bb, b := i.b, on=.(a)]
}
proc.time()[[3L]]-p
#[1] 1.1

Zusammenführungsliste #4370

library(data.table)
aa = data.table(a = seq(1,100), b = rep(0, 100))
bb = data.table(a = seq(1,100), b = rep(1, 100))
setindex(aa, a)
setindex(bb, a)
p = proc.time()[[3L]]
for (i in c(1:1000)) {
  mergelist(list(aa, bb), on="a")
}
proc.time()[[3L]]-p
#[1] 0.696

Hallo Jan, OK danke

Je größer die Daten, desto kleiner die Verbesserung, aber andererseits
Je mehr Iterationen, desto besser die Verbesserung
Das eigentliche Problem hängt mit Big Data und einigen Iterationen zusammen – ich habe es geschrieben
Oben

Am Mo, 4. Mai 2020, 00:33 schrieb Jan Gorecki, [email protected] :

Es gibt eine ausstehende PR Nr. 4370
https://github.com/Rdatatable/data.table/pull/4370 , die verwandt ist. Es
kann Join mit weniger Overhead machen, als [ normalerweise auferlegt. Es reduziert die
Timing Ihres Beispiels um den Faktor 2. Je größer die Daten, desto kleiner
die Verbesserung, aber andererseits, je mehr Iterationen, desto besser
Verbesserung. Beachten Sie, dass es keine Möglichkeit gibt, die Spalte während des Joins zu aktualisieren. Sie
Im Grunde müssen Sie während des Joins Spalten hinzufügen und dann so etwas wie verwenden
fcoalesce, aber das sollte performant sein.
Es sollte einmal #4386 etwas mehr Geschwindigkeit bekommen
https://github.com/Rdatatable/data.table/pull/4386 wird ebenfalls zusammengeführt.

Bibliothek(data.table)aa = data.table(a = seq(1.100), b = rep(0, 100))bb = data.table(a = seq(1.100), b = rep(1, 100))
setindex(aa, a)
setindex(bb, a)p = proc.time()[[3L]]for (i in c(1:1000)) {
aa[bb, b := ib, on=.(a)]
}
proc.time()[[3L]]-p#[1] 1.1

Mergelist #4370 https://github.com/Rdatatable/data.table/pull/4370

Bibliothek(data.table)aa = data.table(a = seq(1.100), b = rep(0, 100))bb = data.table(a = seq(1.100), b = rep(1, 100))
setindex(aa, a)
setindex(bb, a)p = proc.time()[[3L]]for (i in c(1:1000)) {
Mergelist(Liste(aa, bb), on="a")
}
proc.time()[[3L]]-p#[1] 0,696


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-623193573 ,
oder abbestellen
https://github.com/notifications/unsubscribe-auth/ABRM7MJR5THRHE3FIXXV3YTRPXWNNANCNFSM4I4ZPREA
.

Ich habe überprüft, ob #4440 (gestern zusammengeführt) dieses Problem behebt, aber es sieht so aus, als ob es das nicht tut. Obwohl die Timings, die ich hier bekomme, ganz anders sind als die von @vk111 gemeldeten Timings, wenn Sie also in der Lage sind, die neueste Entwicklungsversion zu testen und zu sehen, ob es einen Unterschied für Ihren Workflow macht, wäre das hilfreich.
Da Sie unter Windows arbeiten, gibt es eine weitere ausstehende PR, die #4558 schließlich helfen könnte.


Dies ist das allgemeine Skript, das ich in jeder Umgebung ausführe:

library(data.table)
setDTthreads(2) ## vk111 has 4 cores
aa = data.table(a = seq(1,100), b = rep(0, 100))[,  a1 := as.character(a)]
bb = data.table(a = seq(1,100), b = rep(1, 100))[,  a1 := as.character(a)]
setindex(aa, a); setindex(bb, a)
cat("test1\n")
system.time({
for(i in c(1:1000)) {
  aa[bb, b := i.b, on=.(a, a1)] # test1
}})
cat("test2\n")
system.time({
for(i in c(1:1000)) {
  aa[bb, b := i.b, on=.(a)] # test2
}})

Und das sind Umgebungen:

docker run -it --rm r-base:3.4.0
install.packages("https://cran.r-project.org/src/contrib/Archive/data.table/data.table_1.10.4-3.tar.gz", repos=NULL)
test1
   user  system elapsed 
  0.949   0.007   0.957 
test2
   user  system elapsed 
  0.864   0.000   0.864 
docker run -it --rm r-base:3.6.1
install.packages("https://cran.r-project.org/src/contrib/Archive/data.table/data.table_1.12.2.tar.gz", repos=NULL)
test1
   user  system elapsed 
  2.598   0.047   1.350 
test2
   user  system elapsed 
  2.092   0.016   1.062 



md5-e82041eef8382e88332d077bb608b87c



docker run -it --rm r-base:3.6.1
install.packages("data.table", repos="https://Rdatatable.gitlab.io/data.table")
test1
   user  system elapsed 
  1.174   0.045   1.219 
test2
   user  system elapsed 
  0.981   0.024   1.004 

Hallo, ich bin auf Windows

Am Freitag, 26. Juni 2020, 13:19 Uhr schrieb Jan Gorecki, [email protected] :

Ich habe überprüft, ob #4440 https://github.com/Rdatatable/data.table/pull/4440
Beheben Sie dieses Problem, aber es sieht so aus, als wäre dies nicht der Fall. Obwohl Timings ich bekomme
hier sind ganz anders als die von @vk111 gemeldeten Timings
https://github.com/vk111 , wenn Sie also in der Lage sind, die jüngste Entwicklung zu testen
Version, und prüfen Sie, ob dies für Ihren Workflow einen Unterschied macht
hilfreich.
Dies ist das allgemeine Skript, das ich in jeder Umgebung ausführe:

Bibliothek (data.table)
setDTthreads(2) ## vk111 hat 4 Kernesaa = data.table(a = seq(1.100), b = rep(0, 100))[, a1 := as.character(a)]bb = data.table(a = seq(1.100), b = rep(1, 100))[, a1 := as.character(a)]
setindex(aa, a); setindex(bb, a)
Katze ("test1n")
system.time({für(i in c(1:1000)) {
aa[bb, b := ib, on=.(a, a1)] # test1
}})
Katze("test2n")
system.time({für(i in c(1:1000)) {
aa[bb, b := ib, on=.(a)] # test2
}})

Und das sind Umgebungen:

docker run -it --rm r -base:3.4.0
install.packages("https://cran.r-project.org/src/contrib/Archive/data.table/data.table_1.10.4-3.tar.gz", repos=NULL)
test1
Benutzersystem abgelaufen
0,949 0,007 0,957
test2
Benutzersystem abgelaufen
0,864 0,000 0,864

docker run -it --rm r -base:3.6.1
install.packages("https://cran.r-project.org/src/contrib/Archive/data.table/data.table_1.12.2.tar.gz", repos=NULL)
test1
Benutzersystem abgelaufen
2,598 0,047 1,350
test2
Benutzersystem abgelaufen
2,092 0,016 1,062

docker run -it --rm r -base:3.6.1
install.packages("data.table", repos="https://Rdatatable.gitlab.io/data.table")
test1
Benutzersystem abgelaufen
1,174 0,045 1,219
test2
Benutzersystem abgelaufen
0,981 0,024 1,004

Da Sie unter Windows arbeiten, gibt es eine weitere ausstehende PR, die eventuell auftreten könnte
help #4558 https://github.com/Rdatatable/data.table/pull/4558 .


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-650126662 ,
oder abbestellen
https://github.com/notifications/unsubscribe-auth/ABRM7MJLU3XRN5YN37ZVLALRYR727ANCNFSM4I4ZPREA
.

@ vk111 Ja, genau das, wonach ich gefragt habe. Wenn Sie diese 3 Konfigurationen auf Ihrem Windows-Computer überprüfen und sehen könnten, ob es Fortschritte für Sie gibt.

Aber wie ich verstanden habe, ist pr für Windows noch nicht zusammengeführt

Am Freitag, 26. Juni 2020, 20:07 Uhr schrieb Jan Gorecki, [email protected] :

@vk111 https://github.com/vk111 Ja, genau das, wonach ich gefragt habe.
Wenn Sie diese 3 Konfigurationen auf Ihrem Windows-Computer überprüfen und sehen könnten
ob es Fortschritte für Sie gibt.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-650320224 ,
oder abbestellen
https://github.com/notifications/unsubscribe-auth/ABRM7MMDOCNAWARCCDRSU23RYTPVFANCNFSM4I4ZPREA
.

4440 ist bereits integriert und hilft für jedes Betriebssystem. #4558 muss noch zusammengeführt werden.

@vk111 #4558 wurde ebenfalls bereits zusammengeführt

Hallo Jan, ich habe kürzlich deinen Rat befolgt - #4419
https://github.com/Rdatatable/data.table/issues/4419 im Zusammenhang mit meinem Problem
Also habe ich nicht genau dieses Stück Code mit den Zeichen verbindet
Aber trotzdem danke für diese Verbesserung, ich bin mir sicher, dass es sehr helfen wird
Menschen in der Zukunft, wenn Sie glauben, dass es die bessere Leistung hat als ich
Ich denke, Sie sollten es einfach zusammenführen
Danke schön

пт, 26 июн. 2020. um 20:29, Jan Gorecki [email protected] :

4440 https://github.com/Rdatatable/data.table/pull/4440 ist bereits vorhanden

zusammengeführt und Hilfe für jedes Betriebssystem. #4558
https://github.com/Rdatatable/data.table/pull/4558 steht noch aus
verschmelzen.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-650330154 ,
oder abbestellen
https://github.com/notifications/unsubscribe-auth/ABRM7MIN2P7BXMKG74Z7EKTRYTSIJANCNFSM4I4ZPREA
.

--
Mit freundlichen Grüßen,
Wassili Kusnezow

@vk111 erwähnte PRs sind bereits zusammengeführt. Die Sache ist, zu wissen, ob dieses Problem behoben oder zumindest verbessert wurde. Diese zusammengeführten PRs haben nicht versucht, dieses Problem zu lösen, aber sie sind verwandt, sodass sie möglicherweise hilfreich waren.

Es kommt vor, dass das ursprünglich gemeldete Minimalbeispiel das Problem nur unzureichend dargestellt hat. Basierend auf @vk111 https://github.com/Rdatatable/data.table/issues/3928#issuecomment -538681316 habe ich ein Beispiel erstellt, das deutlich zeigt, dass hier ein Problem vorliegt.

install.packages("https://cran.r-project.org/src/contrib/Archive/data.table/data.table_1.10.4-3.tar.gz", repos=NULL)
install.packages("https://cran.r-project.org/src/contrib/Archive/data.table/data.table_1.12.2.tar.gz", repos=NULL)
install.packages("data.table", repos="https://Rdatatable.gitlab.io/data.table")
library(data.table)
setDTthreads(2L)
set.seed(108)
n2 = 1:366000
n1 = sample(n2, 30000)
d1=data.table(id1=paste0("id",sample(n1)), id2=paste0("id",sample(n1)), v1=n1)
d2=data.table(id1=paste0("id",sample(n2)), id2=paste0("id",sample(n2)), v2=n2)
system.time(d2[d1, v1 := i.v1, on=c("id1","id2")])



md5-e82041eef8382e88332d077bb608b87c



# 3.4.0: 1.10.4-3
   user  system elapsed 
  0.144   0.000   0.144 
# 3.4.0: 1.12.2
   user  system elapsed 
  0.611   0.003   0.451 
# 3.4.0: 1.12.9
   user  system elapsed 
  0.611   0.000   0.452 



md5-e82041eef8382e88332d077bb608b87c



# 4.0.0: 1.10.4-3
   user  system elapsed 
  0.203   0.008   0.211 
# 4.0.0: 1.12.9
   user  system elapsed 
  0.812   0.004   0.644 

verbose zeigt, dass die meiste Zeit mit Calculated ad hoc index in 0.611s elapsed (0.769s cpu) verbracht wird, was ein Aufruf von forderv von bmerge ist.

Ja genau
Aber es scheint, dass es bei diesen Tests keine Verbesserung gibt?

Am Di, 30.06.2020, 00:45 schrieb Jan Gorecki, [email protected] :

Es kommt vor, dass das anfangs gemeldete Minimalbeispiel schlecht belichtet war
die Angelegenheit. Basierend auf @vk111 https://github.com/vk111 #3928 (Kommentar)
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-538681316
Ich habe ein Beispiel erstellt, das deutlich zeigt, dass hier ein Problem vorliegt.

Bibliothek (data.table)
setDTthreads(2L)
set.seed(108)n2 = 1:366000n1 = probe(n2, 30000)d1=data.table(id1=paste0("id",sample(n1)), id2=paste0("id",sample(n1) ), v1=n1)d2=data.table(id1=paste0("id",sample(n2)), id2=paste0("id",sample(n2)), v2=n2)
system.time(d2[d1, v1 := i.v1, on=c("id1","id2")])

3.4.0: 1.10.4-3

Benutzersystem abgelaufen
0,144 0,000 0,144

3.4.0: 1.12.2

Benutzersystem abgelaufen
0,611 0,003 0,451

3.4.0: 1.12.9

Benutzersystem abgelaufen
0,611 0,000 0,452

4.0.0: 1.12.9

Benutzersystem abgelaufen
0,812 0,004 0,644


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-651408089 ,
oder abbestellen
https://github.com/notifications/unsubscribe-auth/ABRM7MPQHSOEGLXS625BU3TRZEKSBANCNFSM4I4ZPREA
.

Keine Verbesserung, das ist immer noch ein Problem.
Nach einigem Graben fand ich, dass der Engpass dieser Anruf ist
https://github.com/Rdatatable/data.table/blob/ba32f3cba38ec270587e395f6e6c26a80be36be6/src/forder.c#L282
weitergehen...
diese Schleife ist für 60% verantwortlich
https://github.com/Rdatatable/data.table/blob/ba32f3cba38ec270587e395f6e6c26a80be36be6/src/forder.c#L242 -L245
und die für 30%
https://github.com/Rdatatable/data.table/blob/ba32f3cba38ec270587e395f6e6c26a80be36be6/src/forder.c#L252 -L258

Ich habe versucht zu prüfen, ob die Verwendung von R-Interna ( CHAR() eher ein Makro als eine Funktion) hier helfen würde, aber es hilft nicht.


Noch minimaleres Beispiel, Timing nur forderv , nur auf R 4.0

install.packages("https://cran.r-project.org/src/contrib/Archive/data.table/data.table_1.10.4-3.tar.gz", repos=NULL)
library(data.table)
setDTthreads(1L)
set.seed(108)
n2 = 1:366000
d2=data.table(id1=paste0("id",sample(n2)), id2=paste0("id",sample(n2)), v2=n2)
system.time(data.table:::forderv(d2, c("id1","id2")))
install.packages("data.table", repos="https://Rdatatable.gitlab.io/data.table")
library(data.table)
setDTthreads(1L)
set.seed(108)
n2 = 1:366000
d2=data.table(id1=paste0("id",sample(n2)), id2=paste0("id",sample(n2)), v2=n2)
system.time(data.table:::forderv(d2, c("id1","id2")))



md5-e82041eef8382e88332d077bb608b87c



# 4.0.2: 1.10.4-3
   user  system elapsed 
  0.198   0.000   0.198 
# 4.0.2: 1.12.9
   user  system elapsed 
  0.393   0.000   0.392 

Ich habe versucht zu prüfen, ob die Verwendung von R-Interna (CHAR() ein Makro statt einer Funktion) hier helfen würde, aber es hilft nicht.

Das liegt daran, dass R das nicht mehr tut. Bei USE_RINTERNALS sind INTEGER, REAL und ich nehme an, auch CHAR sind immer noch Inline-Funktionen. Mit anderen Worten, der Vorteil (dh Makro statt Funktion) von USE_RINTERNALS wurde in neueren Versionen von R entfernt, um ALTREP zuzulassen. Ich glaube nicht, dass es wirklich den Unterschied macht, ob es ein Makro oder eine Funktion oder eine Inline-Funktion an sich ist. Es ist das, was von R innerhalb dieser Arbeitseinheit getan wird. Früher machte USE_RINTERNALS es zu einem Makro und es war eine direkte Speichersuche (eine Array-Dereferenzierung, die nur den Header des Vektors berücksichtigt), weshalb es schneller war. Es war eine sehr leichte Arbeitseinheit. Heutzutage muss R mindestens einen Zweig auf ALTREP prüfen, und selbst bei der Verzweigungsvorhersage summiert sich diese zusätzliche Arbeit und/oder verhindert den Vorabruf. Mit anderen Worten, R hat jetzt etwas mehr Code in diesen Inline-Funktionen. Ich habe keine Benchmark-Beweise, nur Theorie, die darauf basiert, es zu betrachten.

Die Hauptursache könnte das Entfernen des folgenden Zweigs in cradix_r sein
https://github.com/Rdatatable/data.table/blob/76bb569fd7736b5f89471a35357e6a971ae1d424/src/forder.c#L780 -L783
und jetzt gibt es für den Eingang der Länge 2 keinen Kurzschluss.
Es ist nicht offensichtlich, wie dieser Zweig jetzt platziert werden soll, da sich die Funktion in Bezug auf ihre Funktionsweise stark verändert hat.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen