Можете ли вы распараллелить агрегирование с data.table
? да.
Стоит ли оно того? НЕТ. Это ключевой момент, который не удалось выделить в предыдущем ответе.
Как объясняет Мэтт Доул в data.table и parallel computing, копии (" фрагменты ") должны быть созданы перед распределением при параллельном выполнении операций. Это замедляет работу. В некоторых случаях, когда вы не можете использовать data.table
(например, выполняете множество линейных регрессий), стоит разделить задачи между ядрами. Но не агрегация - по крайней мере, когда задействовано data.table
.
Короче (и пока не будет доказано обратное) агрегируйте с помощью data.table
и не беспокойтесь о потенциальном увеличении скорости с помощью doMC
. data.table
уже работает быстро по сравнению со всем остальным, когда дело доходит до агрегирования, даже если оно не многоядерное!
Вот несколько тестов, которые вы можете запустить для себя, сравнивая data.table
внутреннее агрегирование с использованием by
с foreach
и mclapply
. Результаты указаны первыми.
#-----------------------------------------------
# TL;DR FINAL RESULTS (Best to Worst)
# 3 replications, N = 10000:
# (1) 0.007 -- data.table using `by`
# (2) 3.548 -- mclapply with rbindlist
# (3) 5.557 -- foreach with rbindlist
# (4) 5.959 -- foreach with .combine = "rbind"
# (5) 14.029 -- lapply
# ----------------------------------------------
library(data.table)
## And used the following to create the dt
N <- 1e4
set.seed(1)
a = sample(1:N, N*2, replace = TRUE)
b = sample(c("3m","2m2d2m","3m2d1i3s2d","5m","4m","9m","1m"), N*2, replace = TRUE)
d = sample(c("3m","2m2d2m","3m2d1i3s2d","5m","4m","9m","1m"), N*2, replace = TRUE)
e = a
dt = data.table(a = a, b = b, d = d, e = e, key="a")
setkey(dt, "a")
# TEST AGGREGATION WITHOUT PARALLELIZATION ---------------------------
## using data.tables `by` to aggregate
round(rowMeans(replicate(3, system.time({
dt[,list(b = paste(b, collapse=""), d = paste(d, collapse=""), e = e[1], by=a)]
}))), 3)
# [1] 0.007 elapsed for N == 10,000, length(unique(dt[["a"]])) == 8617
## using `lapply`
round(rowMeans(replicate(3, system.time({
results <- lapply(unique(dt[["a"]]), function(x) {
dt[.(x), list(b = paste(b, collapse=""), d = paste(d, collapse=""), e = e[1])]
})
rbindlist(results)
}))), 3)
# [1] 14.029 elapsed for N == 10,000
# USING `mclapply` FORKING ---------------------------------
## use mclapply
round(rowMeans(replicate(3, system.time({
results <- mclapply(unique(dt[["a"]]),
function(x) {
dt[.(x), list(b = paste(b, collapse=""), d = paste(d, collapse=""), e = e[[1]])]
}, mc.cores=4)
rbindlist(results)
}))), 3)
# [1] 3.548 elapsed for N == 10,000
# PARALLELIZATION USING `doMC` PACKAGE ---------------------------------
library(doMC)
mc = 4
registerDoMC(cores=mc)
getDoParWorkers()
# [1] 4
## (option a) by Ricardo Saporta
round(rowMeans(replicate(3, system.time({
foreach(x=unique(dt[["a"]]), .combine="rbind", .inorder=FALSE) %dopar%
dt[.(x) ,list(b = paste(b, collapse=""), d = paste(d, collapse=""), e = e[[1]])]
}))), 3)
# [1] 5.959 elapsed for N == 10,000
## (option b) by Ricardo Saporta
round(rowMeans(replicate(3, system.time({
results <-
foreach(x=unique(dt[["a"]])) %dopar%
dt[.(x) ,list(b = paste(b, collapse=""), d = paste(d, collapse=""), e = e[[1]])]
rbindlist(results)
}))), 3)
# [1] 5.557 elapsed for N == 10,000
registerDoSEQ()
getDoParWorkers()
# [1] 1
person
Danton Noriega
schedule
23.06.2015
list
,c
иpaste
. И какова функция этого кода. Извлекаем ли мы столбцы из фреймов данных или работаем над data.tables? Каковы структуры 'block.read.parent.cigar' и других входных переменных ..... объясните эту проблему лучше! (Очевидно, кто-то еще согласен. Это не мой голос против.) - person IRTFM   schedule 30.09.2013read.index
является индексом строки, то, конечно, группировка каждой строки в строку сама по себе будет медленной. Вы будете звонитьpaste
миллионы раз. Вы использовалиRprof
? Вы использовалиverbose=TRUE
? И вы используете такие слова, как "слишком медленно", не называя цифр. Фактически, я уговорил себя проголосовать против него сейчас. Это можно изменить, если вы улучшите вопрос. - person Matt Dowle   schedule 30.09.2013S
вSNOTE
;) - person Ricardo Saporta   schedule 06.10.2013