【发布时间】:2017-01-11 00:58:40
【问题描述】:
我尝试报告我在mclapply 中遇到的关于不允许大返回值的错误。
显然该错误已在开发版本中修复,但我对响应者的评论更感兴趣:
序列化对象的大小有 2GB 的限制,例如mclapply 可以从分叉的进程返回,此示例正在尝试 16GB。这在 R-devel 中已被取消(对于 64 位构建),但这种用法非常不寻常且效率很低(该示例需要 ca 150GB,因为(取消)序列化涉及的所有副本)
如果使用 mclapply 对大数据进行并行计算效率低下,那么有什么更好的方法呢?我做这种事情的需求只会越来越大,而且我肯定到处都遇到瓶颈。我看到的教程是关于如何使用函数的非常基本的介绍,但不一定是如何有效地使用函数来管理权衡。该文档对这种权衡有一个小小的介绍:
mc.preschedule:如果设置为“TRUE”,则计算首先被划分 到(最多)有多少工作有核心,然后 作业开始,每个作业可能涵盖多个 价值。如果设置为“FALSE”,则为每个作业派生一个作业 “X”的值。前者更适合短期计算或 ‘X’中的大量值,后者更适合工作 完成时间差异较大且数量不多 “X”的值与“mc.cores”的比较
和
默认情况下(‘mc.preschedule = TRUE’)输入‘X’被分割成 与核心一样多的部分(当前值已传播 依次跨核心,即核心 1 的第一个值,第二个 到核心 2,...(核心 + 1)-th 值到核心 1 等),然后是一个 进程被分叉到每个核心并收集结果。
如果没有预先安排,则为每个值派生一个单独的作业 'X'。确保运行的作业不超过“mc.cores” 一次,一旦这个数字被分叉,主进程就会等待 让孩子在下一次分叉前完成
可靠地对这些事物进行基准测试需要花费大量时间,因为有些问题只会在规模上体现出来,然后很难弄清楚到底发生了什么。因此,更好地了解函数的行为会很有帮助。
编辑:
我没有具体的示例,因为我经常使用 mclapply,并且想更好地了解如何考虑性能影响。虽然写入磁盘可以解决错误,但我认为这对于必须发生的(反)序列化没有帮助,这也必须通过磁盘 IO。
一个工作流程如下:
取一个大的稀疏矩阵M,并将其分块写入磁盘(比如M1-M100),因为M 本身不适合内存。
现在说,对于I 中的每个用户i,M 中有Ci 列,我想在用户级别添加和聚合。对于较小的数据,这将是相对微不足道的:
m = matrix(runif(25), ncol=5)
df = data.frame(I=sample(1:6, 20, replace=T), C=sample(1:5, 20, replace=T))
somefun = function(m) rowSums(m)
res = sapply(sort(unique(df$I)), function(i) somefun(m[,df[df$I == i,]$C]))
但是对于更大的数据,我的方法是根据列所在的矩阵M1-M100 将用户/列的 data.frame 拆分为不同的 data.frames,对这些 data.frames 执行并行循环,读取在关联的矩阵中,然后循环遍历用户,提取列并应用我的函数,然后获取输出列表,然后再次循环并重新聚合。
如果我有一个不能像那样重新聚合的函数(到目前为止,这不是问题),这并不理想,但我显然用这种方法洗牌了太多数据。
【问题讨论】:
-
在不了解问题的结构的情况下,很难说出如何才能做得更好。我在错误报告中查看了您的示例,这可能只是为了证明您无法返回大对象。您可能想查看共享内存包。您需要发布一个最小的可重现示例,该示例可以捕获您的问题的结构,但又足够简单易懂。我认为工作安排(如
mc.preschedule)不会让你有任何收获。 -
我已经发布了一个简单的例子来说明我正在做的事情,但复杂性来自于磁盘 IO、序列化和此类问题所发生的一切。我想要做的事情清楚吗?
标签: r parallel-processing overhead mclapply