Data.table: opération de jointure presque 2 fois plus lente

Créé le 2 oct. 2019  ·  29Commentaires  ·  Source: Rdatatable/data.table

Salut, j'étais en train de tester
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)

et ont remarqué que l'opération de jointure était presque 2 fois plus lente dans la nouvelle version data.table (R?)
Je pense que cela dépend principalement de la version de data.table

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

Tous les 29 commentaires

Avoir exécuté ce qui suit :

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

Ensuite, faites ce qui suit pour créer ce tracé

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
}]


Après avoir commencé, j'ai réalisé que je pouvais rationaliser un peu cela en utilisant

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)

pour ajouter le temps de commit directement au benchmark

join_timings.txt

Salut MichaelChirico, j'ai lu deux fois
mais que signifie exactement la chronologie de 2016 à 2019 ? Est-ce une version de datatable ?

pas seulement des versions mais des commits spécifiques. laissez-moi essayer d'ajouter une démarcation des versions, une bonne idée que j'ai oublié d'ajouter

@MichaelChirico votre graphique a l'air super cool, ce qui manquait était une interprétation de cela :) En devinant, je dirais que le nouveau forder parallèle est plus lent pour une entrée de longueur 100 qu'il ne l'était auparavant. Quel IMO est bien, car ce sont encore des microsecondes. Il vaut bien sûr la peine de réduire les frais généraux, mais la priorité doit être une réduction des ressources dans les scénarios d'utilisation les plus courants. Boucler 10 000 fois sur une entrée de longueur 100 n'en fait certainement pas partie.

c'était aussi ma supposition après avoir regardé les NOUVELLES 1.12.0. va essayer de réexécuter un thread unique.

@jangorecki , si vous faites le calcul simple, ce sont des milliers de microsecondes, c'est-à-dire des millisecondes
L'inspiration de ce test était mon projet actuel où je joins 7-8 tables de multiplication avec 40 000 lignes
Avant ça prend 18 secondes, après ça prend 40 secondes
Mon test comprend également la clé de caractère
J'ai installé 3.6 + 1.12 puis je l'ai ramené à 3.4 + 1.10
Je pense que ce n'est pas une situation normale, c'est pourquoi ce problème est ici

Oui, le graphique est vraiment génial; nous devrions faire plus de cela et l'automatiser.

Mais le rapport original compare R 3,4 à R 3,6, qui a R 3,5 au milieu. Nous savons que R 3.5 a eu un impact sur data.table via le changement d'ALTREP de REAL(), INTEGER() des macros aux fonctions (légèrement plus lourdes).

@ vk111 Pouvez-vous s'il vous plaît réexécuter vos tests avec la v1.12.4 maintenant sur CRAN. Rien de mieux? Nous avons pris R API en dehors des boucles pour faire face à R 3.5+. Comme prochaine étape, il serait bon de savoir comment vous trouvez la v1.12.4. Pouvez-vous également inclure plus d'informations sur votre machine ; par exemple le système d'exploitation, la RAM et le nombre de CPU.

@matt , fera l'affaire

Salut @mattdowle ,

J'ai mis à jour vers 1.12.4 (+R 3.6.1) - fondamentalement, il y a les mêmes numéros pour le test unitaire et ma fonction
Je ne considérerai ici que les jointures avec caractère sans indexation - comme référence
Test unitaire (comme mentionné dans le premier message)
3.6.1 : 6,87 s sans index
3.4.0 : 3,02 s (pas d'index)

Ma fonction du projet reste la même : 20 vs 40 secondes
Il ne consiste qu'en ~14 dt se joint
deux tableaux 30 000 lignes (dt1) et 366 000 lignes (dt2)
15 colonnes chacune
la clé est composée de 2 caractères et 1 chiffre
et assigné 7 champs (de dt1 à dt2) lors de la jointure

mon ordinateur:
Win 10 64 bits
AMD A8 2.2Ghz
8 Go de RAM

cmd : wmic cpu obtenir NumberOfCores, NumberOfLogicalProcessors/ Format : Liste
NombreDeCores=4
NumberOfLogicalProcessors=4

Merci pour votre analyse

Salut @mattdowle alors envisagez-vous cela ?

Selon un git bisect que je viens de relancer, ce commit est "coupable" pour le ralentissement, j'espère que cela pourra aider Matt à identifier la racine. Le fait qu'il soit lié à forder me rend relativement sûr que nous l'avons correctement identifié.

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

Plus précisément:

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

Avec ces deux scripts, à partir de master/HEAD :

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

Ensuite, à chaque itération, exécutez sh run_join_time.sh et vérifiez le résultat. Les commits bad prenaient environ 0,9 seconde par itération sur ma machine, les commits good environ 0,7.

Salut Michael, merci, mais les performances ont chuté de façon spectaculaire, en particulier
pour la clé de caractère-j'ai fourni avec le test unitaire dans le tout premier post
Quoi qu'il en soit, je pense que nous devons attendre la confirmation de Matt si c'est corrigé dans
nouvelle version ou pas

Le jeudi 26 décembre 2019 à 15:02, Michael Chirico [email protected]
a écrit:

Selon un git bisect que je viens de relancer, ce commit est "coupable" pour le
ralentir, j'espère que cela aidera Matt à cerner la racine. que c'est
lié à forder me rend relativement confiant que nous l'avons épinglé
correctement.

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

Plus précisément:

run_join_time.sh

INSTALLER R CMD . && Rscript time_join.R

time_join.R

bibliothèque (data.table)
bibliothèque (microbenchmark)

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

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

Avec ces deux scripts, depuis master/HEAD :

git checkout 1.12.0
git début de la bissectrice
git bisect mauvais
git bisect bon 1.11.8

Ensuite, à chaque itération, exécutez sh run_join_time.sh et vérifiez le résultat. le
les mauvais commits prenaient environ 0,9 seconde par itération sur ma machine,
bon engage environ .7.


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/Rdatatable/data.table/issues/3928?email_source=notifications&email_token=ABRM7MJQITNUZDNYV7NTIX3Q2S2ORA5CNFSM4I4ZPREKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZ66HVTR4Q6#issuecomment-566,36
ou désabonnez-vous
https://github.com/notifications/unsubscribe-auth/ABRM7MOTZRFFM2QKVFUHT6LQ2S2ORANCNFSM4I4ZPREA
.

>

Meilleures salutations,
Vassili Kouznetsov

@vk111 si ce problème n'est pas résolu, vous pouvez supposer en toute sécurité que le problème n'est pas encore résolu. Chaque fois que nous réparons quelque chose, nous fermons le problème connexe.

@ vk111 , vous pourrez peut-être atténuer avec quelques ajustements mineurs en utilisant setkey au lieu de setindex . Cela réduit votre test de plus de moitié sur mon ordinateur :

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

Salut Cole, oui je connais setkey - j'ai fourni ci-dessus la courte description
de mon projet et il n'y a pas de but de 1000 jointures - il y en a entre 10 et 20
se joint et le fait est que mes chaînes de caractères sont très dynamiques et je
besoin de faire setkey à chaque fois avant de rejoindre comme 20 fois setkey et 20
fois rejoint et donc le gain de temps est inférieur à 2 fois
Je vis avec 3.4.0 pendant un certain temps comme solution de contournement générale pour cette situation
et ce n'est probablement pas un gros problème pour le réparer dans la nouvelle version, surtout si
il y a un coupable trouvé
Soit dit en passant, si nous comparons des pommes avec des pommes, je pense que 3,4 (1,10) sera
toujours plus rapide que 3.6 (1.12) si j'utilise le même test unitaire avec le setkey pour
les deux versions
Joyeuses fêtes

Le dimanche 29 décembre 2019, 14h48, Cole Miller, [email protected] a écrit :

@ vk111 https://github.com/vk111 vous pourrez peut-être atténuer avec certains
modifications mineures utilisant setkey au lieu de setindex. Cela réduit votre test de
plus de la moitié sur mon ordinateur :

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()
pour(je dans c(1:1000)) {
aa[bb, b := ib, on=.(a, a1)] # test1 sans clé
}
toc()

4 secondes écoulées

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

pour(je dans c(1:1000)) {
aa[bb, b := ib] # test2 sans clé
}
toc()

1,46 s écoulée

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

bibliothèque (microbenchmark)
bibliothèque (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 = copier(aa)
bb_nokey = copier(bb)

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

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

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

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

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

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

boîte à moustaches(
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)
)
)


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/Rdatatable/data.table/issues/3928?email_source=notifications&email_token=ABRM7MPU64YBK7UNT3O3OYDQ3CTBRA5CNFSM4I4ZPREKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHY73VA#5comment-5729issuecomment-5729
ou désabonnez-vous
https://github.com/notifications/unsubscribe-auth/ABRM7MKSP6LCUJD2HOAG7D3Q3CTBRANCNFSM4I4ZPREA
.

Il y a un PR #4370 en attente qui est lié. Il peut faire une jointure avec moins de surcharge que [ impose normalement. Cela réduit le timing de votre exemple d'un facteur 2. Plus les données sont volumineuses, plus l'amélioration est faible, mais d'un autre côté, plus il y a d'itérations, meilleure est l'amélioration. Notez qu'il n'y a aucun moyen de mettre à jour la colonne pendant la jointure. Vous devez essentiellement ajouter des colonnes lors de la jointure, puis utiliser quelque chose comme fcoalesce , mais cela devrait être performant.
Il devrait s'accélérer une fois que #4386 sera également fusionné.

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

liste de fusion #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

Salut Jan, d'accord merci

Plus les données sont volumineuses, plus l'amélioration est faible, mais d'un autre côté,
plus il y a d'itérations, meilleure est l'amélioration
Le vrai problème est lié au big data et à quelques itérations - je l'ai écrit
au dessus

Le lundi 4 mai 2020, 00:33 Jan Gorecki, [email protected] a écrit :

Il y a un PR #4370 en attente
https://github.com/Rdatatable/data.table/pull/4370 qui est lié. Ce
peut faire une jointure avec moins de surcharge que [ impose normalement. Il réduit la
chronométrage de votre exemple par un facteur de 2. Plus les données sont volumineuses, plus
l'amélioration, mais d'un autre côté, plus il y a d'itérations, mieux c'est
amélioration. Notez qu'il n'y a aucun moyen de mettre à jour la colonne pendant la jointure. Vous
doivent essentiellement ajouter des colonnes lors de la jointure, puis utiliser quelque chose comme
fcoalesce, mais cela devrait être performant.
Il devrait obtenir une vitesse supplémentaire une fois # 4386
https://github.com/Rdatatable/data.table/pull/4386 sera également fusionné.

bibliothèque(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

liste de fusion # 4370 https://github.com/Rdatatable/data.table/pull/4370

bibliothèque(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


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-623193573 ,
ou désabonnez-vous
https://github.com/notifications/unsubscribe-auth/ABRM7MJR5THRHE3FIXXV3YTRPXWNNANCNFSM4I4ZPREA
.

J'ai vérifié si # 4440 (fusionné hier) résout ce problème, mais il semble que ce ne soit pas le cas. Bien que les horaires que j'obtiens ici soient assez différents des horaires rapportés par @ vk111 , donc si vous êtes en mesure de tester la version de développement récente et de voir si cela fait une différence pour votre flux de travail, cela serait utile.
Comme vous êtes sur Windows, il y a un autre PR en attente qui pourrait éventuellement aider #4558.


Voici le script commun que j'exécute dans chaque environnement :

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

Et ce sont des environnements:

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 

Bonjour, je suis sous Windows

Le ven. 26 juin 2020, 13 h 19, Jan Gorecki, [email protected] a écrit :

J'ai vérifié si # 4440 https://github.com/Rdatatable/data.table/pull/4440
résoudre ce problème, mais il semble que ce ne soit pas le cas. Bien que les horaires que je reçois
ici sont assez différents des horaires rapportés par @ vk111
https://github.com/vk111 , donc si vous êtes en mesure de tester le développement récent
version, et voyez si cela fait une différence pour votre flux de travail qui serait
utile.
Voici le script commun que j'exécute dans chaque environnement :

bibliothèque (data.table)
setDTthreads(2) ## vk111 a 4 cœursaa = 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)
chat("test1n")
system.time({for(i in c(1:1000)) {
aa[bb, b := ib, on=.(a, a1)] # test1
}})
chat("test2n")
system.time({for(i in c(1:1000)) {
aa[bb, b := ib, on=.(a)] # test2
}})

Et ce sont des environnements:

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
système utilisateur écoulé
0,949 0,007 0,957
test2
système utilisateur écoulé
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
système utilisateur écoulé
2,598 0,047 1,350
test2
système utilisateur écoulé
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
système utilisateur écoulé
1,174 0,045 1,219
test2
système utilisateur écoulé
0,981 0,024 1,004

Comme vous êtes sur Windows, il y a un autre PR en attente qui pourrait éventuellement
aide #4558 https://github.com/Rdatatable/data.table/pull/4558 .


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-650126662 ,
ou désabonnez-vous
https://github.com/notifications/unsubscribe-auth/ABRM7MJLU3XRN5YN37ZVLALRYR727ANCNFSM4I4ZPREA
.

@ vk111 Oui, exactement ce que je demandais. Si vous pouviez vérifier ces 3 configurations sur votre machine Windows et voir s'il y a des progrès pour vous.

Mais comme je l'ai compris pr pour Windows n'est pas encore fusionné

Le ven. 26 juin 2020, 20 h 07, Jan Gorecki, [email protected] a écrit :

@ vk111 https://github.com/vk111 Oui, exactement ce que je demandais.
Si vous pouviez vérifier ces 3 configurations sur votre machine Windows et voir
s'il y a des progrès pour vous.


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-650320224 ,
ou désabonnez-vous
https://github.com/notifications/unsubscribe-auth/ABRM7MMDOCNAWARCCDRSU23RYTPVFANCNFSM4I4ZPREA
.

4440 est déjà fusionné et aide pour chaque système d'exploitation. #4558 est toujours en attente de fusion.

@vk111 #4558 a également été fusionné

Salut Jan, j'ai suivi ton conseil récemment - #4419
https://github.com/Rdatatable/data.table/issues/4419 lié à mon problème
donc je n'ai pas ce morceau de code exact avec les caractères se joint
Mais de toute façon merci pour cette amélioration, je suis sûr que cela aidera beaucoup de
les gens à l'avenir si vous pensez qu'il a les meilleures performances alors je
suppose que vous devriez simplement le fusionner
Merci

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

4440 https://github.com/Rdatatable/data.table/pull/4440 est déjà

fusionné et aide pour chaque système d'exploitation. #4558
https://github.com/Rdatatable/data.table/pull/4558 est toujours en attente de
fusionner.


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-650330154 ,
ou désabonnez-vous
https://github.com/notifications/unsubscribe-auth/ABRM7MIN2P7BXMKG74Z7EKTRYTSIJANCNFSM4I4ZPREA
.

--
Meilleures salutations,
Vassili Kouznetsov

@vk111 a mentionné que les PR sont déjà fusionnés. Le tout est de savoir si ce problème a été résolu, ou du moins amélioré. Ces relations publiques fusionnées n'essayaient pas de résoudre ce problème, mais elles sont liées et auraient donc pu être utiles.

Il se trouve que l'exemple minimal rapporté initialement exposait mal le problème. Basé sur le @ vk111 https://github.com/Rdatatable/data.table/issues/3928#issuecomment -538681316 j'ai construit un exemple qui montre clairement qu'il y a un problème ici.

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 montre que la plupart du temps est dépensé Calculated ad hoc index in 0.611s elapsed (0.769s cpu) , qui est un appel à forderv depuis bmerge .

Oui, exactement
Mais il semble qu'il n'y ait pas d'amélioration dans ces tests ?

Le mar. 30 juin 2020, 00:45 Jan Gorecki, [email protected] a écrit :

Il se trouve que l'exemple minimal rapporté initialement exposait mal
le problème. Basé sur le @vk111 https://github.com/vk111 #3928 (commentaire)
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-538681316
J'ai construit un exemple qui montre clairement qu'il y a un problème ici.

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

3.4.0 : 1.10.4-3

système utilisateur écoulé
0,144 0,000 0,144

3.4.0 : 1.12.2

système utilisateur écoulé
0,611 0,003 0,451

3.4.0 : 1.12.9

système utilisateur écoulé
0,611 0,000 0,452

4.0.0 : 1.12.9

système utilisateur écoulé
0,812 0,004 0,644


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-651408089 ,
ou désabonnez-vous
https://github.com/notifications/unsubscribe-auth/ABRM7MPQHSOEGLXS625BU3TRZEKSBANCNFSM4I4ZPREA
.

Pas d'amélioration, c'est toujours un problème.
Après quelques recherches, j'ai trouvé que le goulot d'étranglement est cet appel
https://github.com/Rdatatable/data.table/blob/ba32f3cba38ec270587e395f6e6c26a80be36be6/src/forder.c#L282
aller plus loin...
cette boucle est responsable de 60%
https://github.com/Rdatatable/data.table/blob/ba32f3cba38ec270587e395f6e6c26a80be36be6/src/forder.c#L242 -L245
et ceux pour 30%
https://github.com/Rdatatable/data.table/blob/ba32f3cba38ec270587e395f6e6c26a80be36be6/src/forder.c#L252 -L258

J'ai essayé de vérifier si l'utilisation des composants internes de R ( CHAR() une macro plutôt qu'une fonction) aiderait ici, mais cela n'aide pas.


Exemple encore plus minimal, synchronisation forderv uniquement, sur R 4.0 uniquement

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 

J'ai essayé de vérifier si l'utilisation des composants internes de R (CHAR() une macro plutôt qu'une fonction) aiderait ici, mais cela n'aide pas.

C'est parce que R ne le fait plus. Avec USE_RINTERNALS, INTEGER, REAL et je suppose que CHAR aussi, sont toujours des fonctions en ligne. En d'autres termes, l'avantage (c'est-à-dire la macro au lieu de la fonction) de USE_RINTERNALS a été supprimé dans les versions récentes de R pour permettre ALTREP. Je ne crois pas que ce soit vraiment la macro, la fonction ou la fonction en ligne, en soi, qui fait la différence. C'est ce qui est fait par R à l'intérieur de cette unité de travail. Auparavant, USE_RINTERNALS en faisait une macro et c'était une recherche directe en mémoire (un déréférencement de tableau prenant simplement en compte l'en-tête du vecteur), c'est pourquoi c'était plus rapide. C'était une unité de travail très légère. De nos jours, R a au moins une branche pour vérifier ALTREP et, même avec la prédiction de branche, ce travail supplémentaire s'additionne et/ou empêche la prélecture. En d'autres termes, R a maintenant un peu plus de code à l'intérieur de ces fonctions en ligne. Je n'ai aucune preuve de référence, juste une théorie basée sur l'examen.

La cause principale peut être la suppression de la branche suivante dans cradix_r
https://github.com/Rdatatable/data.table/blob/76bb569fd7736b5f89471a35357e6a971ae1d424/src/forder.c#L780 -L783
et maintenant pour l'entrée de longueur 2 il n'y a pas de court-circuit.
Il n'est pas évident de savoir comment placer cette branche maintenant, car la fonction a beaucoup changé en termes de fonctionnement.

Cette page vous a été utile?
0 / 5 - 0 notes