data.table lapply .SD随着列数的增加而急剧减速

时间:2017-06-10 06:24:03

标签: r performance data.table

我有一个20k x 60k的表用于聚合,我正在尝试使用高内存使用效率和速度效率的方法。我注意到data.table的速度随着列数的增加而急剧下降。例如:

library(data.table)  
# a 200 x 1,000 table.
test_dt= data.table(sample= rep(1:100,2), value= matrix(sample(6e07, 2e05), nrow = 200 ))
system.time(test_dt[, lapply(.SD, mean), by= sample, .SDcols= colnames(test_dt)[-1]])
#   user  system elapsed 
#  0.470   0.009   0.117 

# a 200 x 10, 000 table
test_dt= data.table(sample= rep(1:100,2), value= matrix(sample(6e07, 2e06), nrow = 200 ))
system.time(test_dt[, lapply(.SD, mean), by= sample, .SDcols= colnames(test_dt)[-1]])
#   user  system elapsed 
# 15.055   0.603  15.334 

关于这种非线性(100倍减速超过10倍列)的任何解释都会增加?解决这个问题的一种方法是将其融化为长DT。但是,它会占用更多的内存。有没有办法实现内存使用和速度之间的协调?感谢。

1 个答案:

答案 0 :(得分:3)

我看到与OP类似的结果:

# a 200 x 10, 000 table
set.seed(1)
test_dt= data.table(sample= rep(1:100,2), value= matrix(sample(6e07, 2e06), nrow = 200 ))[, 
  (2:10001) := lapply(.SD, as.numeric), .SDcols=2:10001]
system.time(z <- test_dt[, lapply(.SD, mean), by= sample])
#    user  system elapsed 
#   12.27    0.00   12.26

(我转换为数字,因为它非常清楚,这些将被视为浮点数;并添加set.seed以便在必要时比较结果更容易。)< / p>

  

关于这种非线性(100倍减速超过10倍列)的任何解释都会增加?

通常,data.tables和data.frames经过优化,可以支持将行/观察分组在一起,而不是迭代大量的列。我猜你的方法已经达到RAM限制并使用交换内存......虽然我对此并不是很了解。

我认为如果您想从data.table包的速度中充分受益,您可能需要遵循其自然存储格式。如下所示,它有显着的不同。

  

解决这个问题的一种方法是将其融入长DT。但是,它会占用更多的内存。有没有办法实现内存使用和速度之间的协调?

我认为最好的方法是获得更多内存并保持数据的长篇。我看到熔化的表大约是两倍大小,但计算速度却快了100倍。

test_mdt = melt(test_dt, id = "sample")[, variable := match(variable, unique(variable))]

system.time(mz <- test_mdt[, .(res = mean(value)), by=.(sample, variable)])
#    user  system elapsed 
#    0.11    0.00    0.11 

object.size(test_dt)  # 17.8 MB
object.size(test_mdt) # 32.0 MB

或者,如果每个样本具有相同的大小,请使用矩阵列表或数组:

test_dt[, g := rowid(sample)]
test_mats = lapply( split(test_dt[, !"sample"], by="g", keep.by=FALSE), as.matrix )
system.time(matz <- Reduce(`+`, test_mats)/length(test_mats))
#    user  system elapsed 
#       0       0       0 

object.size(test_mats) # 17.3 MB