Data.table: операция присоединения почти в 2 раза медленнее

Созданный на 2 окт. 2019  ·  29Комментарии  ·  Источник: Rdatatable/data.table

Привет, я тестировал
data.table_1.10.4-3 + версия R 3.4.0 (21 апреля 2017 г.)
против
data.table_1.12.2 + версия R 3.6.1 (05.07.2019)

и заметил, что операция соединения почти в 2 раза медленнее в новой версии data.table (R?)
Я думаю, в основном зависит от версии 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

Все 29 Комментарий

Запустили следующее:

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

Затем сделал следующее, чтобы создать этот сюжет

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


После запуска я понял, что могу немного упростить это, используя

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)

чтобы добавить время фиксации непосредственно в тест

join_timings.txt

Привет, MichaelChirico, я прочитал дважды
но что именно означает временная шкала с 2016 по 2019 год? Это версия datatable?

не только версии, но и конкретные коммиты. позвольте мне попробовать добавить некоторое разграничение версий, хорошая идея, которую я забыл добавить

@MichaelChirico ваш график выглядит очень круто, чего не хватало, так это интерпретации этого :) Предполагая, что новый параллельный фордер работает медленнее для ввода длины 100, чем это было раньше. Что IMO прекрасно, потому что это все еще микросекунды. Конечно, стоит уменьшить накладные расходы, но приоритетом должно быть сокращение ресурсов в наиболее распространенных сценариях использования. Цикл 10000 раз на входе длины 100 определенно не один из них.

это тоже было моим предположением после просмотра 1.12.0 NEWS. попытается повторно запустить однопоточный.

@jangorecki , если вы сделаете простую математику, это тысячи микросекунд, то есть миллисекунды.
Вдохновением для этого теста послужил мой текущий проект, в котором я соединяю таблицы 7-8 раз с 40 000 строк.
До того, как это займет 18 секунд, после того, как это займет 40 секунд
Мой тест также включает символьный ключ
Установил 3.6+1.12 и потом откатился на 3.4+1.10
Я думаю, что это ненормальная ситуация, поэтому эта проблема здесь.

Да, график действительно потрясающий; мы должны делать больше и автоматизировать это.

Но в исходном отчете R 3,4 сравнивается с R 3,6, где в середине находится R 3,5. Мы знаем, что R 3.5 повлиял на data.table через изменение ALTREP REAL(), INTEGER() с макросов на (немного более тяжелые) функции.

@ vk111 Не могли бы вы повторить свои тесты с v1.12.4 сейчас на CRAN. Лучше? Мы использовали внешние циклы R API, чтобы справиться с R 3.5+. В качестве следующего шага было бы здорово узнать, как вы находите v1.12.4. Можете ли вы также включить дополнительную информацию о вашей машине; например, операционная система, оперативная память и количество процессоров.

@матовый , сделаю

Привет @mattdowle ,

Я обновился до 1.12.4 (+R 3.6.1) - в основном для юнит-теста и моей функции используются одни и те же числа.
Я буду рассматривать здесь только соединения с символом без индексации - как ориентир
Модульный тест (как указано в первом посте)
3.6.1: 6,87 с без индекса
3.4.0: 3,02 с (без индекса)

Моя функция из проекта остается прежней: 20 против 40 секунд
Он состоит всего из ~14 dt соединений.
две таблицы 30 000 строк (dt1) и 366 000 строк (dt2)
по 15 столбцов в каждом
ключ состоит из 2 символов и 1 цифры
и назначил 7 полей (от dt1 до dt2) во время соединения

мой компьютер:
Вин 10 64 бит
AMD A8 2,2 ГГц
8 ГБ оперативной памяти

cmd: wmic cpu get NumberOfCores, NumberOfLogicalProcessors/ Format: List
Количество ядер = 4
Количество логических процессоров = 4

Спасибо за ваш анализ

Привет, @mattdowle , ты думаешь об этом?

Согласно git bisect , который я только что перезапустил, этот коммит «виновен» в замедлении, надеюсь, это поможет Мэтту определить причину. То, что это связано с forder , делает меня относительно уверенным, что мы правильно его определили.

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

Точнее:

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

С помощью этих двух скриптов из master/HEAD :

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

Затем на каждой итерации запускайте sh run_join_time.sh и проверяйте результат. Коммиты bad занимали примерно 0,9 секунды на итерацию на моей машине, коммиты good около 0,7.

Привет, Майкл, спасибо, но производительность резко упала, особенно
для символьного ключа я предоставил модульный тест в самом первом сообщении
В любом случае, я думаю, нам нужно дождаться подтверждения от Мэтта, исправлено ли это в
новая версия или нет

В четверг, 26 декабря 2019 г., в 15:02, Майкл Кирико[email protected]
написал:

Согласно git bisect, который я только что перезапустил, этот коммит «виновен» в
замедление, надеюсь, это поможет Мэтту найти корень. что это
связанные с Фордером, вселяют в меня уверенность, что мы определились с этим
правильно.

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

Точнее:

run_join_time.sh

R КОМАНДА УСТАНОВИТЬ . && Rscript time_join.R

time_join.R

библиотека (данные.таблица)
библиотека (микробенчмарк)

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

сводка (микробенчмарк (время = 1000L, aa[bb, b := ib, on=.(a)])$time/1e6)

С помощью этих двух скриптов из master/HEAD:

git-касса 1.12.0
git начало пополам
git пополам плохо
git bisect хорошо 1.11.8

Затем на каждой итерации запускайте sh run_join_time.sh и проверяйте результат. То
плохие коммиты занимали примерно 0,9 секунды на итерацию на моей машине,
хорошо совершает около 0,7.


Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/Rdatatable/data.table/issues/3928?email_source=notifications&email_token=ABRM7MJQITNUZDNYV7NTIX3Q2S2ORA5CNFSM4I4ZPREKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHVTR4Q#6906,6-6-6906comment ,
или отписаться
https://github.com/notifications/unsubscribe-auth/ABRM7MOTZRFFM2QKVFUHT6LQ2S2ORANCNFSM4I4ZPREA
.

>

С наилучшими пожеланиями,
Василий Кузнецов

@ vk111 , если эта проблема не закрыта, вы можете смело предположить, что проблема еще не решена. Всякий раз, когда мы исправляем что-то, мы закрываем связанную проблему.

@ vk111 vk111 вы можете смягчить некоторые незначительные изменения, используя setkey вместо setindex . Это сокращает ваш тест более чем вдвое на моем компьютере:

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

Привет, Коул, да, я знаю о setkey - я привел краткое описание выше.
моего проекта и нет цели 1000 присоединений - есть 10-20
присоединяется, и дело в том, что мои строки символов очень динамичны, и я
нужно делать setkey каждый раз перед присоединением, например, 20 раз setkey и 20
раз присоединяется и поэтому выигрыш во времени меньше чем в 2 раза
Я живу с 3.4.0 какое-то время как общий обходной путь для этой ситуации
и, вероятно, это не проблема исправить в новой версии, особенно если
найден виновный коммит
Кстати, если сравнивать яблоки с яблоками, я думаю, что 3.4(1.10) будет
все еще быстрее, чем 3.6 (1.12), если я использую тот же модульный тест с setkey для
обе версии
Счастливых праздников

Вс, 29 декабря 2019 г., 14:48 Коул Миллер, уведомления@github.com написал:

@vk111 https://github.com/vk111 вы можете смягчить некоторые
небольшие изменения с использованием setkey вместо setindex. Это сокращает ваш тест на
более половины на моем компьютере:

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

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

тик()
для (я в с (1: 1000)) {
aa[bb, b := ib, on=.(a, a1)] # test1 без ключа
}
ток()

прошло 4 сек.

тик()
setkey(аа, а, а1)
setkey(bb, a, a1)

для (я в с (1: 1000)) {
aa[bb, b := ib] # test2 без ключа
}
ток()

Прошло 1,46 сек.

[изображение: изображение]
https://user-images.githubusercontent.com/57992489/71557665-126d7880-2a17-11ea-8664-21a10deb47ca.png

библиотека (микробенчмарк)
библиотека (данные.таблица)

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

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

aa_nokey = копия (аа)
bb_nokey = копировать (бб)

тик()
aa_int_key = setkey (копия (аа), а)
bb_int_key = setkey (копировать (bb), а)
ток()

тик()
aa_int_char = setkey (копия (аа), а, а1)
bb_int_char = setkey (копия (bb), a, a1)
ток()
int_nokey = функция (dt1, dt2) {
dt1[dt2, b := ib, on=.(a)]
}

int_key = функция (dt1, dt2) {
dt1[dt2, b := ib]
}

int_char_nokey = функция (dt1, dt2) {
dt1[dt2, b := ib, on=.(a, a1)]
}

int_char_key = функция (dt1, dt2) {
dt1[dt2, b := ib]
}

int_char_key_on = функция (dt1, dt2) {
dt1[dt2, b := ib, on=.(a, a1)]
}

ящичковая диаграмма (
микробенчмарк(
a_no_key = int_nokey (аа, бб),
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)
)
)


Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/Rdatatable/data.table/issues/3928?email_source=notifications&email_token=ABRM7MPU64YBK7UNT3O3OYDQ3CTBRA5CNFSM4I4ZPREKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHY73VA#500comment ,
или отписаться
https://github.com/notifications/unsubscribe-auth/ABRM7MKSP6LCUJD2HOAG7D3Q3CTBRANCNFSM4I4ZPREA
.

Существует ожидающий PR # 4370, который связан. Это может сделать соединение с меньшими накладными расходами, которые обычно налагает [ . Это сокращает время вашего примера в 2 раза. Чем больше данных, тем меньше улучшение, но, с другой стороны, чем больше итераций, тем лучше улучшение. Обратите внимание, что нет возможности обновить столбец во время соединения. В основном вам нужно добавлять столбцы во время соединения, а затем использовать что-то вроде fcoalesce , но это должно быть эффективным.
Он должен получить дополнительную скорость, как только # 4386 также будет объединен.

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

список слияния # 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

Привет, Ян, хорошо, спасибо

Чем больше данных, тем меньше улучшение, но, с другой стороны,
чем больше итераций, тем лучше улучшение
Настоящая проблема связана с большими данными и несколькими итерациями — это я написал
выше

Пн, 4 мая 2020 г., 00:33 Ян Горецки, уведомления@github.com написал:

Ожидается PR № 4370.
https://github.com/Rdatatable/data.table/pull/4370 , который связан. Это
может сделать соединение с меньшими накладными расходами, которые обычно накладывает [. Это уменьшает
время вашего примера в 2 раза. Чем больше данных, тем меньше
улучшение, но с другой стороны, чем больше итераций, тем лучше
улучшение. Обратите внимание, что нет возможности обновить столбец во время соединения. Ты
в основном нужно добавлять столбцы во время соединения, а затем использовать что-то вроде
fcoalesce, но это должно работать.
Он должен получить дополнительную скорость один раз # 4386
https://github.com/Rdatatable/data.table/pull/4386 также будут объединены.

библиотека (data.table) aa = data.table (a = seq (1100), b = rep (0, 100)) bb = data.table (a = seq (1100), b = rep (1, 100))
setindex(аа, а)
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

список слияния # 4370 https://github.com/Rdatatable/data.table/pull/4370

библиотека (data.table) aa = data.table (a = seq (1100), b = rep (0, 100)) bb = data.table (a = seq (1100), b = rep (1, 100))
setindex(аа, а)
setindex(bb, a)p = proc.time()[[3L]]for (i in c(1:1000)) {
список слияния (список (аа, бб), на = "а")
}
proc.time()[[3L]]-p#[1] 0,696


Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-623193573 ,
или отписаться
https://github.com/notifications/unsubscribe-auth/ABRM7MJR5THRHE3FIXXV3YTRPXWNNANCNFSM4I4ZPREA
.

Я проверил, решает ли #4440 (объединенный вчера) эту проблему, но похоже, что это не так. Хотя время, которое я получаю здесь, сильно отличается от времени, о котором сообщает @vk111 , поэтому, если вы можете протестировать последнюю версию разработки и посмотреть, имеет ли это какое-либо значение для вашего рабочего процесса, это было бы полезно.
Поскольку вы работаете в Windows, есть еще один ожидаемый PR, который в конечном итоге может помочь # 4558.


Это общий сценарий, который я запускаю в каждой среде:

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

А это среды:

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 

Привет, я на Windows

Пт, 26 июня 2020 г., 13:19 Ян Горецки, уведомления@github.com написал:

Я проверил, если # 4440 https://github.com/Rdatatable/data.table/pull/4440
решить эту проблему, но, похоже, это не так. Хотя тайминги я получаю
здесь сильно отличаются от таймингов, о которых сообщил @vk111
https://github.com/vk111 , поэтому, если вы можете протестировать недавнюю разработку
версия, и посмотреть, имеет ли это какое-либо значение для вашего рабочего процесса, который будет
полезный.
Это общий сценарий, который я запускаю в каждой среде:

библиотека (данные.таблица)
setDTthreads(2) ## vk111 имеет 4 ядраsaa = 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(бб, а)
кошка("test1n")
system.time ({для (я в c (1: 1000)) {
aa[bb, b := ib, on=.(a, a1)] # test1
}})
кошка("test2n")
system.time ({для (я в c (1: 1000)) {
aa[bb, b := ib, on=.(a)] # test2
}})

А это среды:

docker run -it --rm r- база: 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)
тест1
пользовательская система истекла
0,949 0,007 0,957
тест2
пользовательская система истекла
0,864 0,000 0,864

docker run -it --rm r- база: 3.6.1
install.packages("https://cran.r-project.org/src/contrib/Archive/data.table/data.table_1.12.2.tar.gz", repos=NULL)
тест1
пользовательская система истекла
2,598 0,047 1,350
тест2
пользовательская система истекла
2,092 0,016 1,062

docker run -it --rm r- база: 3.6.1
install.packages("data.table", repos="https://Rdatatable.gitlab.io/data.table")
тест1
пользовательская система истекла
1,174 0,045 1,219
тест2
пользовательская система истекла
0,981 0,024 1,004

Поскольку вы находитесь в Windows, есть еще один ожидаемый PR, который в конечном итоге может
справка № 4558 https://github.com/Rdatatable/data.table/pull/4558 .


Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-650126662 ,
или отписаться
https://github.com/notifications/unsubscribe-auth/ABRM7MJLU3XRN5YN37ZVLALRYR727ANCNFSM4I4ZPREA
.

@ vk111 Да, именно то, о чем я спрашивал. Если бы вы могли проверить эти 3 конфигурации на своем компьютере с Windows и посмотреть, есть ли какой-либо прогресс для вас.

Но как я понял пр для винды еще не слит

Пт, 26 июня 2020 г., 20:07 Ян Горецки, уведомления@github.com написал:

@vk111 https://github.com/vk111 Да, именно то, о чем я спрашивал.
Если бы вы могли проверить эти 3 конфигурации на вашем компьютере с Windows и увидеть
если есть прогресс для вас.


Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-650320224 ,
или отписаться
https://github.com/notifications/unsubscribe-auth/ABRM7MMDOCNAWARCCDRSU23RYTPVFANCNFSM4I4ZPREA
.

4440 уже объединен и помогает для каждой ОС. # 4558 все еще ожидает слияния.

@vk111 #4558 тоже уже объединен

Привет Ян, я недавно последовал твоему совету - # 4419
https://github.com/Rdatatable/data.table/issues/4419 , связанные с моей проблемой
поэтому у меня нет именно этого фрагмента кода с объединением символов
Но в любом случае спасибо за это улучшение, я уверен, что оно многим поможет.
люди в будущем, если вы считаете, что он имеет лучшую производительность, чем я
думаю, вы должны просто объединить его
Спасибо

пт, 26 июн. 2020 г. в 20:29, Ян Горецки уведомления@github.com :

4440 https://github.com/Rdatatable/data.table/pull/4440 уже есть

объединены и помогают для каждой ОС. №4558
https://github.com/Rdatatable/data.table/pull/4558 все еще ожидает
сливаться.


Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-650330154 ,
или отписаться
https://github.com/notifications/unsubscribe-auth/ABRM7MIN2P7BXMKG74Z7EKTRYTSIJANCNFSM4I4ZPREA
.

--
С наилучшими пожеланиями,
Василий Кузнецов

@ vk111 упомянутые PR уже объединены. Дело в том, чтобы знать, была ли эта проблема решена или, по крайней мере, улучшена. Эти объединенные PR не пытались решить эту проблему, но они связаны между собой, поэтому могли быть полезными.

Случается, что изначально представленный минимальный пример плохо раскрывает проблему. На основе @vk111 https://github.com/Rdatatable/data.table/issues/3928#issuecomment -538681316 я построил пример, который ясно показывает, что здесь есть проблема.

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 показывает, что большую часть времени тратится Calculated ad hoc index in 0.611s elapsed (0.769s cpu) , что является вызовом forderv из bmerge .

Да, точно
Но, кажется, нет никаких улучшений в этих тестах?

Во вторник, 30 июня 2020 г., 00:45 Ян Горецки, уведомления@github.com написал:

Бывает, что изначально заявленный минимальный пример плохо экспонировался
проблема. На основе @vk111 https://github.com/vk111 #3928 (комментарий)
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-538681316
Я построил пример, который ясно показывает, что здесь есть проблема.

библиотека (данные.таблица)
установитьDTthreads(2L)
set.seed(108)n2 = 1:366000n1 = образец(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

пользовательская система истекла
0,144 0,000 0,144

3.4.0: 1.12.2

пользовательская система истекла
0,611 0,003 0,451

3.4.0: 1.12.9

пользовательская система истекла
0,611 0,000 0,452

4.0.0: 1.12.9

пользовательская система истекла
0,812 0,004 0,644


Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/Rdatatable/data.table/issues/3928#issuecomment-651408089 ,
или отписаться
https://github.com/notifications/unsubscribe-auth/ABRM7MPQHSOEGLXS625BU3TRZEKSBANCNFSM4I4ZPREA
.

Никаких улучшений, это все еще проблема.
После некоторых копаний я обнаружил, что узкое место - это вызов
https://github.com/Rdatatable/data.table/blob/ba32f3cba38ec270587e395f6e6c26a80be36be6/src/forder.c#L282
идти дальше...
этот цикл отвечает за 60%
https://github.com/Rdatatable/data.table/blob/ba32f3cba38ec270587e395f6e6c26a80be36be6/src/forder.c#L242 -L245
а те на 30%
https://github.com/Rdatatable/data.table/blob/ba32f3cba38ec270587e395f6e6c26a80be36be6/src/forder.c#L252 -L258

Я попытался проверить, поможет ли здесь использование внутренних компонентов R ( CHAR() макрос, а не функция), но это не помогает.


Еще более минимальный пример, время только forderv , только на 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 

Я попытался проверить, поможет ли здесь использование внутренних компонентов R (CHAR() макроса, а не функции), но это не помогает.

Это потому, что R больше так не делает. С USE_RINTERNALS, INTEGER, REAL и я предполагаю, что CHAR также являются встроенными функциями. Другими словами, преимущество (т. е. макрос вместо функции) USE_RINTERNALS было удалено в последних версиях R, чтобы разрешить ALTREP. Я не верю, что на самом деле имеет значение макрос, функция или встроенная функция как таковая. Это то, что делает R внутри этой единицы работы. В старые времена USE_RINTERNALS делал его макросом, и это был прямой поиск в памяти (разыменование массива только с учетом заголовка вектора), поэтому он был быстрее. Это была очень легкая единица работы. В наши дни у R есть по крайней мере одна ветвь для проверки на ALTREP, и даже с предсказанием ветвлений эта дополнительная работа добавляет и/или предотвращает предварительную выборку. Другими словами, в R теперь есть немного больше кода внутри этих встроенных функций. У меня нет эталонных доказательств, только теория, основанная на их рассмотрении.

Основной причиной может быть удаление следующей ветки в cradix_r
https://github.com/Rdatatable/data.table/blob/76bb569fd7736b5f89471a35357e6a971ae1d424/src/forder.c#L780 -L783
и теперь для входа длины 2 короткого замыкания нет.
Теперь не очевидно, как разместить эту ветку, потому что функция сильно изменилась с точки зрения того, как она работает.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги