使用 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.tableby 一起使用时是否使用多线程? 如果有,是否存在启用/禁用多线程的条件? 有没有一种方法可以让用户“强制”data.table 在此处使用多线程?

仅供参考,当我导入 data.table 时,我看到一半的内核启用了多线程,所以我想这里没有 openMP 问题。

【问题讨论】:

也许,您可以通过verbose = TRUE 了解更多有关内部运作的详细信息。 不是专家,但您可以使用setDTthreads(threads = 0) 设置线程数(“0”表示使用所有线程;您也可以指定精确的线程数)。如果你想检查正在使用的线程数:getDTthreads() 【参考方案1】:

我从 data.table github 的 data.table 开发人员那里得到了答案。

总结如下:

查找by 变量组本身总是并行化的,但更重要的是,

如果j 上的函数是通用的(用户定义函数),则没有并行化。

如果函数为(gforce) optimized,则j 上的操作将并行化(j 中的表达式仅包含函数minmaxmeanmedianvarsdsum, 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 并行化/多线程的主要内容,如果未能解决你的问题,请参考以下文章

一行 Python 实现并行化 -- 日常多线程操作的新思路

Java 单元测试 - 并行化 + 多线程 + 无限次

多进程 MPI 与多线程 std::thread 性能

[转]TestNG的多线程并行

VS 7.1 Release 编译和多线程

5天玩转C#并行和多线程编程