我尝试报告我在mclapply中遇到的关于不允许大返回值的错误。
显然,该错误已在开发版本中得到修复,但我对响应者的评论更感兴趣:
序列化对象的大小有 2GB 的限制,例如 mclapply 可以从分叉的进程返回,本示例尝试 16GB。这在 R-devel 中已被取消(对于 64 位版本),但这种用法非常不寻常且效率很低(该示例需要 ca 150GB,因为(取消)序列化涉及的所有副本)
如果使用 mclapply 对大数据进行并行计算效率低下,那么有什么更好的方法呢?我做这种事情的需求只会越来越大,而且我肯定到处都遇到瓶颈。我看到的教程是关于如何使用函数的非常基本的介绍,但不一定是如何有效地使用函数来管理权衡。该文档对这种权衡有一个小小的介绍:
mc.preschedule:如果设置为 'TRUE',则计算首先被划分为(最多)有多少个作业有核心,然后开始作业,每个作业可能覆盖多个值。如果设置为“FALSE”,则为每个“X”值派生一个作业。前者更适合短计算或'X'中的大量值,后者更适合完成时间差异较大且'X'值与'mc.cores'相比没有太多的工作</p>
和
默认情况下('mc.preschedule = TRUE')输入'X'被分成与核心一样多的部分(当前值按顺序分布在核心中,即第一个值到核心1,第二个到核心2,...... .. (core + 1)-th value to core 1 etc.) 然后将一个进程分叉到每个核心并收集结果。
在没有预先安排的情况下,会为每个“X”值派生一个单独的作业。为了确保一次运行的作业不超过“mc.cores”,一旦该数量被分叉,主进程会在下一次分叉之前等待子进程完成
可靠地对这些事物进行基准测试需要花费大量时间,因为有些问题只会在规模上体现出来,然后很难弄清楚到底发生了什么。因此,更好地了解函数的行为会很有帮助。
编辑:
我没有具体的例子,因为我经常使用 mclapply 并且想更好地了解如何考虑性能影响。虽然写入磁盘可以解决错误,但我认为这对于必须发生的(反)序列化没有帮助,这也必须通过磁盘 IO。
一个工作流程如下:获取一个大的稀疏矩阵M
,并将其分块写入磁盘(例如M1-M100
),因为 M 本身不适合内存。
现在说,对于其中的每个用户,我想在用户级别添加和聚合i
其中I
的Ci
列。M
对于较小的数据,这将是相对微不足道的:
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]))
但是对于更大的数据,我的方法是根据列所在的矩阵将用户/列的 data.frame 拆分为不同的 data.frames M1-M100
,对这些 data.frames 执行并行循环,读入关联的矩阵,然后然后遍历用户,提取列并应用我的函数,然后获取输出列表,再次循环并重新聚合。
如果我有一个不能像那样重新聚合的函数(到目前为止,这不是问题),这并不理想,但我显然用这种方法洗牌了太多数据。