使用 data.table 并行化/多线程
Posted
技术标签:
【中文标题】使用 data.table 并行化/多线程【英文标题】:Parallelizing / Multithreading with data.table 【发布时间】:2021-11-27 01:33:30 【问题描述】:我有一个超过 10 亿个观测值的大数据,我需要执行一些速度很慢的字符串操作。
我的代码就这么简单:
DT[, var := some_function(var2)]
如果我没记错的话,data.table
在使用by
调用时会使用多线程,我正在尝试利用它来并行化此操作。为此,我可以制作一个临时 grouper 变量,例如
DT[, grouper := .I %/% 100]
然后做
DT[, var := some_function(var2), by = grouper]
我尝试使用少量数据样本进行一些基准测试,但令人惊讶的是我没有看到性能提升。所以我的问题是:
data.table
与 by
一起使用时是否使用多线程?
如果有,是否存在启用/禁用多线程的条件?
有没有一种方法可以让用户“强制”data.table
在此处使用多线程?
仅供参考,当我导入 data.table 时,我看到一半的内核启用了多线程,所以我想这里没有 openMP 问题。
【问题讨论】:
也许,您可以通过verbose = TRUE
了解更多有关内部运作的详细信息。
不是专家,但您可以使用setDTthreads(threads = 0)
设置线程数(“0”表示使用所有线程;您也可以指定精确的线程数)。如果你想检查正在使用的线程数:getDTthreads()
【参考方案1】:
我从 data.table github 的 data.table
开发人员那里得到了答案。
总结如下:
查找by
变量组本身总是并行化的,但更重要的是,
如果j
上的函数是通用的(用户定义函数),则没有并行化。
如果函数为(gforce) optimized,则j
上的操作将并行化(j 中的表达式仅包含函数min
、max
、mean
、median
、var
、sd
、 sum
, prod
, first
, last
, head
, tail
)
因此,如果j
上的功能是通用的,建议手动进行并行操作,但它可能并不总是保证速度增益。 Reference
==解决方案==
在我的例子中,当我直接使用 DT[, var := some_function(var2)]
时,我遇到了向量内存耗尽,即使我的服务器有 1TB 的内存,而数据占用了 200GB 的内存。
我使用split(DT, by='grouper')
将我的data.table
拆分成块,并使用doFuture
foreach
%dopar%
来完成这项工作。速度非常快。
【讨论】:
非常感谢您非常有启发性的反馈@Matthew Son以上是关于使用 data.table 并行化/多线程的主要内容,如果未能解决你的问题,请参考以下文章