Распараллелено ли группирование в data.table 1.12.0? - PullRequest
0 голосов
/ 28 января 2019

В журнале изменений data.table v1.12.0 я заметил следующее:

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

Я проверил, могу ли я ускоритьнекоторая группировка, но безуспешно.Я сделал несколько разных тестов, и я всегда получаю одинаковые результаты.Действительно ли группирование распараллелено?Может я не правильно использую параметры потока?Как видите, data.table был скомпилирован с openmp, в противном случае setDTthread напечатайте сообщение, чтобы сообщить пользователю, что поддержка openmp не поддерживается.Вот воспроизводимый пример одного из моих тестов.

library(data.table)

n = 5e6
k = 1e4

DT = data.table(x = runif(n), y = runif(n), grp = sample(1:k, n, TRUE))

# Any function not too fast
f = function(x,y) as.list(eigen(cov(cbind(x,y)), only.values = TRUE)$value)

setDTthreads(1)
getDTthreads()
#> [1] 1

system.time(DT[ , f(x,y), by = grp])
#> utilisateur     système      écoulé 
#>       3.365       0.008       3.374

setDTthreads(0)
getDTthreads(T)
#> omp_get_max_threads() = 4
#> omp_get_thread_limit() = 2147483647
#> DTthreads = 0
#> RestoreAfterFork = true
#> [1] 4

system.time(DT[ , f(x,y), by = grp])
#> utilisateur     système      écoulé 
#>       3.324       0.029       3.238

Создан в 2019-01-27 пакетом Представить (v0.2.1)

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Да, группировка распараллелена в v 1.12.0

Ваш эталонный тест - немного красной сельди.Вы хотите fast f(x, y), если вы хотите изолировать скорость группировки.Используя количество элементов в ваших примерах, но с помощью тривиальной функции мы получим:

library(data.table)
  packageVersion("data.table")
#> [1] '1.12.0'

n = 5e6
N <- n
k = 1e4

print(getDTthreads())
#> [1] 12

DT = data.table(x = rep_len(runif(n), N),
                y = rep_len(runif(n), N),
                grp = rep_len(sample(1:k, n, TRUE), N))
bench::system_time(DT[, .(a = 1L), by = "grp"])
#>   process      real 
#> 250.000ms  72.029ms

setDTthreads(1)

bench::system_time(DT[, .(a = 1L), by = "grp"])
#>   process      real 
#> 125.000ms 126.385ms

Создано в 2019-02-01 пакетом представлением (v0.2.1)

То есть мы были немного быстрее в параллельном случае, но только примерно на 50 мс - ничтожно мало по сравнению с 3 с вашей функции.

Если мы увеличим размерDT, мы можем увидеть более существенную разницу:

library(data.table)
  packageVersion("data.table")
#> [1] '1.12.0'

n = 5e6
N <- 1e9
k = 1e4

print(getDTthreads())
#> [1] 12

DT = data.table(x = rep_len(runif(n), N),
                y = rep_len(runif(n), N),
                grp = rep_len(sample(1:k, n, TRUE), N))
bench::system_time(DT[, .(a = 1L), by = "grp"])
#> process    real 
#> 45.719s 14.485s

setDTthreads(1)

bench::system_time(DT[, .(a = 1L), by = "grp"])
#> process    real 
#> 24.859s 24.890s
sessioninfo::session_info()
#> - Session info ----------------------------------------------------------
#>  setting  value                       
#>  version  R version 3.5.2 (2018-12-20)
#>  os       Windows 10 x64              
#>  system   x86_64, mingw32             
#>  ui       RTerm                       
#>  language (EN)                        
#>  collate  English_Australia.1252      
#>  ctype    English_Australia.1252      
#>  tz       Australia/Sydney            
#>  date     2019-02-01                  
#> 

Создано в 2019-02-01 с помощью пакета Представить (v0.2.1)

0 голосов
/ 31 января 2019

Здесь ответ, не подтвержденный какими-либо полномочиями (например, членом команды data.table), основанный на моем исследовании проблем data.table из репозитория github.

Из вопроса # 3042 Я понимаю, что sum и mean оптимизированы.Мы можем сравнить его, чтобы убедиться в его правильности:

library(data.table)
n = 1e7 ; k = 1e5
DT = data.table(x = runif(n), y = runif(n), grp = sample(1:k, n, TRUE))

setDTthreads(1)
system.time(DT[ , mean(x), by = grp]) #> 0.8 s
setDTthreads(0)
system.time(DT[ , mean(x), by = grp]) #> 0.4 s

Однако Мэтт Доул в том же выпуске # 3042 писал:

Осталось многосделать на расширение на другие функции Gforce и группирование произвольных функций

И в # 3130 sritchie73 писал

Стоит отметить, что функции R по своей природене потокобезопасны, например, поэтому они не могут быть переданы в многопоточный код C ++ через Rcpp.

Итак, похоже, что распараллеливание пользовательских функций не простая задача, и в настоящее время нет реализациив data.table.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...