mclapply与大型对象 - "序列化太大,无法存储在原始向量中"

13

我一直在使用multicore包处理大型对象时遇到问题。基本思路是我正在使用Bioconductor函数(readBamGappedAlignments)读取大型对象。我有一个文件名的字符向量,并且我一直在使用mclapply来循环读取这些文件并将它们读取到列表中。该函数大致如下:

objects <- mclapply(files, function(x) {
  on.exit(message(sprintf("Completed: %s", x)))
  message(sprintf("Started: '%s'", x))
  readBamGappedAlignments(x)
}, mc.cores=10)

然而,我一直收到以下错误:Error: serialization is too large to store in a raw vector。不过,似乎我可以独自读取同样的文件而没有此错误。我在这里找到了有关此问题的提及,但没有解决方法。

如果有任何并行解决方案建议将不胜感激 - 这必须是并行完成的。我可以考虑使用snow,但我有一台非常强大的服务器,拥有15个处理器、每个处理器8个内核和256GB的内存可以完成此任务。我宁愿在这台机器上跨核心进行操作,而不是使用我们的一个集群。


2
您可以在一台机器上使用Socket Cluster来与Snow交互('localhost'是默认设置)。 - Joshua Ulrich
10
出错的原因是在父级尝试从子级检索数据时,数据被转换为一个类型为raw的向量,而且这个向量比R语言最长的向量2^31-1还要长。尝试将更多的工作放在函数内部,这样结果就是将大数据“缩减(reduction)”了。 - Martin Morgan
非常感谢Martin!我怀疑这可能与此有关,但认为它会表现为另一条错误消息。再次出现未使用R_len_t的问题...如果我们可以将其设置为长整型并完成它,那就太好了。 - Vince
你可以考虑使用 foreach,不过我不是很清楚长向量出现在哪里。如果没有其他办法,你也可以将对象分区,以便通过将每个大约2^30个项目拆分为新列来将长向量映射到矩阵中。 - Iterator
你能回溯错误,以便我们知道它发生的确切位置吗? - zipizip
也许Martin应该把他的评论转换成答案?考虑到我们拥有的信息,这可能是最好的建议了。 - Seth
1个回答

3
据传说,整数限制很快就会在R中得到解决。 在我的经验中,这个限制可能会阻塞具有不到20亿个单元格(约为最大整数)的数据集,以及像multicore包中的sendMaster这样的低级函数依赖于传递原始向量。我有大约1百万个进程,代表了约4亿行和8亿个单元格的数据表格式,在mclapply将结果发送回来时,它遇到了这个限制。
采用分而治之的策略并不难,并且有效。我意识到这是一个hack方法,我们应该能够依赖于mclapply。
创建一个列表的列表而不是一个大列表,其中每个子列表都比破碎版本小,然后将它们分成几个部分喂给mclapply。将此称为file_map。结果是一个列表的列表,因此您可以使用特殊的双重连接do.call函数。结果,每次mclapply完成时,序列化原始向量的大小都是可以管理的。
只需循环处理较小的块:
collector = vector("list", length(file_map)) # more complex than normal for speed 

for(index in 1:length(file_map)) {
reduced_set <- mclapply(file_map[[index]], function(x) {
      on.exit(message(sprintf("Completed: %s", x)))
      message(sprintf("Started: '%s'", x))
      readBamGappedAlignments(x)
    }, mc.cores=10)
collector[[index]]= reduced_set

}

output = do.call("c",do.call('c', collector)) # double concatenate of the list of lists

或者,可以将输出保存到数据库中,例如SQLite。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接