doParallel和foreach无法并行合并操作

doParallel和foreach无法并行合并操作,r,foreach,parallel-processing,doparallel,R,Foreach,Parallel Processing,Doparallel,我正在尝试将一个大的数据.frame与一个小的数据.frame合并,并将计算并行化。下面的代码工作完美,最大限度地利用了我机器的所有核心: len <- 2000000 set.seed(666) dat = paste(sample(letters, len, rep = T), sample(0:9, len, rep = T), sample(letters, len, rep = T), sep = '') # create a vector of strings that are

我正在尝试将一个大的
数据.frame
与一个小的数据.frame合并,并将计算并行化。下面的代码工作完美,最大限度地利用了我机器的所有核心:

len <- 2000000
set.seed(666)
dat = paste(sample(letters, len, rep = T), sample(0:9, len, rep = T), sample(letters, len, rep = T), sep = '') # create a vector of strings that are 3-long
head(dat)
set.seed(777)
num <- sample(0:9, len, replace = T)
bigDF <-  data.frame(dat = dat, num = num)
smallDF <- data.frame(num = 0:9, caps = toupper(letters[1:10]))
startP <- 1
chunk <- 10000
nodes <- detectCores()
cl <- makeCluster(nodes)
registerDoParallel(cl)
mergedList <- foreach(i = 0:(len/chunk - 1)) %dopar% {
    tmpDF = bigDF[(startP + i * chunk):(startP - 1 + (i + 1) * chunk), ]
    merge(tmpDF, smallDF, by = 'num', all.x = T)
}
stopCluster(cl)
为什么会出现这种不一致性,人们如何才能解决它?在特定示例中,如果将
dat
索引为整数,则代码有效。但索引并不是所有情况下的答案。为什么字符串的长度与使用的芯数有关系?

目前还不是答案,但: 如果我运行您的代码,但使用
%do%
以避免并行化,我会得到两种情况下相同(成功)的结果,当然
dat
名称除外。如果我用
%dopar%
运行短名称,用
%do%
运行长名称,则相同

在一个支持包中,这看起来像是一个微妙的bug,因此您可能希望在这个包上ping开发人员

9月29日更新:我使用ClusterMap运行了我认为相同的设置:

dffunc <-function(i=i,bigDF=bigDF,smallDF=smallDF,startP=startP,chunk=chunk) {
tmpDF <- bigDF[(startP + i * chunk):(startP - 1 + (i + 1) * chunk), ]
    merge(tmpDF, smallDF, by = 'num', all.x = T)
    }


clusmerge<- clusterMap(cl,  function(i) {dffunc(i=i)}, 0:(len/chunk-1),MoreArgs=list(bigDF=bigDF,smallDF=smallDF,startP=startP,chunk=chunk) )

因为这样可以挂起整个机器。更好的
cl我认为区别在于,在第一种情况下,“bigDF”的第一列是一个6760级的因子,而在第二种情况下,它有1983234级。拥有大量的级别可能会导致许多性能问题。当我用
stringsAsFactors=FALSE
创建“bigDF”时,性能要好得多

bigDF <- data.frame(dat=dat, num=num, stringsAsFactors=FALSE)

bigDF是否为非工作案例生成子R进程?您的可用内存如何?看来我可以在Win7-64位R3.1.1上重现此问题。吨自由柱塞;Rscript的孩子们永远不会启动。更多新闻:我有千兆字节的可用内存,所以不是问题@卡尔:我的系统规格和你的一样。请注意,奇怪的是,如果
dat
由4个长字符串组成,则第二个核心对计算有部分贡献。对于5长或更长的字符串,只有一个内核在工作。这可能是它的一部分,因为在我的i7机器上,不并行运行任何一种情况(使用
%do%
而不是
%dopar%
)几乎不花时间完成。可能需要花费所有时间的事情是将这些因子级别分配给从内核。我想我们应该做一个配置文件,然后再试一次,但要将该列转换为“角色”。谢谢Steve。iSplitRows绝对值得一看。然而,我特别感兴趣的是最大化所有内核的计算输出,而不仅仅是减少系统时间@卡尔维特霍夫:同样的情况也适用于%do%,我已经这样做了,而且速度更快。字符的计算速度确实比factors快,但仍然只部署了一个核心。confirm-
iSplitRows()
是一个简洁的函数,但对计算中涉及的核心数没有影响。奇怪的是:当我尝试原始设置,但将
bigDF$dat
smallDF$caps
转换为
character
类时,最多有两个内核处于活动状态。当我有机会的时候,我将尝试
mclappy
。@SteveWenston
StringsaCharacters=F
似乎适合我,所有的核心都很吸引人!?我认为,这只受到资源上字符串(而非因素)成本的限制。+1用于明智的
makeCluster(nodes-1)
:-)。clusterMap()在checkForRemoteErrors(val)
中给我一个
错误。只需使用
bigDF运行代码,我从未听说过
makeCluster(detectNodes())
挂起Linux或Mac。由于主处理器不执行任何计算,因此每个内核启动一个工作线程是非常有意义的,这是“mclappy”在多核包中默认所做的。您是说它可以挂起对“makeCluster”的调用还是挂起对后续并行操作的调用?“除了Windows之外,你还看到过其他什么问题吗?”SteveWeston我稍微夸张了一点:因为Rscript集群占用了99.99%的可用CPU,所以几乎所有其他东西都在“等待”等待获得几个周期的机会。是的,当集群完成时,机器将恢复正常,但与此同时,大多数进程必须等待、等待、等待。。。(暗示里克的咖啡馆)我明白你的意思。在集群或专用工作站上使用99.99%的内核被认为是一件好事,但在你的个人笔记本电脑上却很烦人。
nodes <- detectCores()
cl <- makeCluster(nodes)
bigDF <- data.frame(dat=dat, num=num, stringsAsFactors=FALSE)
library(itertools)
mergedList <- foreach(splitDF=isplitRows(bigDF, chunkSize=chunk)) %dopar% {
    merge(splitDF, smallDF, by = 'num', all.x = T)
}