返回列表的长度与在R中使用foreach时从中检索迭代器的向量的长度不匹配

时间:2016-07-05 09:32:45

标签: r foreach parallel-processing

我正在尝试使用foreach包在R中并行处理,但它不能按我的意愿工作。我正在使用我自己创建的函数(Xenopus_Walk),它返回一个向量。现在我想为向量(newly_populated_vec)中保存的每个数字运行此函数,并获得一个列表,该列表存储已创建为所述列表的一个元素的每个向量。我目前使用的命令如下(我想你可以忽略它的大部分内容,因为这主要是我的函数依赖的导出包和参数):

no_cores <- detectCores()-1
cl <- makeCluster(no_cores)
registerDoParallel(cl) 
Xenopus_Data <- foreach(b=1:length(newly_populated_vec),.combine=list,.multicombine=TRUE,.packages = c("raster", "gdistance", "rgdal","sp")) %dopar% { Xenopus_Walk(altdata=altdata,water=water,habitat_suitability=habitat_suitability,max_range_without_water=max_range_without_water,max_range=max_range,slope=slope,Start_Pt=newly_populated_vec[b]) }

我现在遇到的问题是返回列表的长度(Xenopus_Data)与我从(newly_populated_vec)检索迭代器的向量长度不同:

> length(Xenopus_Data)
[1] 47
> length(newly_populated_vec)
[1] 2027

在试图弄清楚什么是错的时候,我已经读过,必须将工作负载分成相等的块并将它们分别传递到核心,但是你可能会告诉我对这一切的理解是非常低的。我的处置总共有32个核心。 有谁知道为什么我有这个问题,也许还有办法解决它?我知道需要可重复的例子,但我使用的功能很长,我怀疑任何人都会通过它。尽管如此,如果我能通过提供更多信息来帮助让事情更清楚,我将很乐意这样做! 非常感谢任何类型的帮助。提前谢谢!

编辑:我忘了添加,当我查看列表时它是嵌套的,所以我没有为向量中的每个数字获得一个元素,但我得到一个具有多个子元素的元素。以防万一有帮助。

1 个答案:

答案 0 :(得分:0)

您不应该使用.combine=list,因为如果结果超过100,则会产生嵌套列表(除非您使用.maxcombine选项指定更大的值)。我已经看过之前使用过的,但我很确定它总是由于对.combine函数的工作原理的误解而完成。

默认行为是返回列表中的所有结果,因此您只需删除.combine.multicombine选项即可解决问题。

这是一个简单的例子,用于演示:

> length(foreach(1:2027, .combine='c') %do% 1:10)
[1] 20270
> length(foreach(1:2027, .combine=list, .multicombine=TRUE) %do% 1:10)
[1] 47
> length(foreach(1:2027) %do% 1:10)
[1] 2027

使用默认的.combine函数,结果始终是一个列表,其长度等于指定的任务数,无论结果的类型如何。

如果您感兴趣,可以使用以下方法明确定义和使用与默认组合函数类似的组合函数:

library(foreach)
# This is defined the same as "foreach:::defcombine"
listcomb <- function(a, ...) {
  # concatenate new results with list of all previous results
  c(a, list(...))
}
r <- foreach(1:101, .combine='listcomb', .init=list(),
    .multicombine=TRUE, .maxcombine=100) %do% {
  list()
}

请注意,您必须指定.init=list(),以便listcomb的第一个参数在第一次调用listcomb时为空列表。如果你不这样做,第一个结果如果恰好是一个列表就会被破坏。