在[r]中使用mclapply,foreach或其他东西并行操作对象?

时间:2012-06-14 15:45:19

标签: r memory foreach parallel-processing fork

有没有办法同时对R中的对象进行操作?我理解mclapply parallel中的numeric进程并将工作空间内容复制到每个进程。相反,我希望让我的核心在一个对象上执行独立的工作,而不必拆分和组合结果。用例是将data.frame中的所有factor列并行更改为b列。另一个用例是具有大量级别的data.frame中的分箱因子。我尝试这样做的主要原因是1)避免内存不足和2)提高速度。

下面,对象a是在data.frame factor中拆分列,然后在应用a后合并它们的结果。相反,我想直接在对象a上操作。在串行中,我可以将factor中的列转换为foreach...%do%类型作为a循环的副作用。与此同时,我无法将factor列转换为foreach...%dopar%类型作为副作用,因为(据我所知)a内部,R指的是每个衍生进程的本地对象。

a <- data.frame(b=c(1,1,2,2), c=c(2,2,3,3)) str(a) > str(a) 'data.frame': 4 obs. of 2 variables: $ b: num 1 1 2 2 $ c: num 2 2 3 3 #serial b <- foreach (i = iter(1:ncol(a)), .combine = data.frame) %do% { a[,i] <- factor(a[,i]) } str(a) str(b) > str(a) 'data.frame': 4 obs. of 2 variables: $ b: Factor w/ 2 levels "1","2": 1 1 2 2 $ c: Factor w/ 2 levels "2","3": 1 1 2 2 > str(b) 'data.frame': 4 obs. of 2 variables: $ result.1: Factor w/ 2 levels "1","2": 1 1 2 2 $ result.2: Factor w/ 2 levels "2","3": 1 1 2 2 #parallel a <- data.frame(b=c(1,1,2,2), c=c(2,2,3,3)) b <- foreach (i = iter(1:ncol(a)), .combine = data.frame) %dopar% { a[,i] <- factor(a[,i]) } str(a) str(b) > str(a) 'data.frame': 4 obs. of 2 variables: $ b: num 1 1 2 2 $ c: num 2 2 3 3 > str(b) 'data.frame': 4 obs. of 2 variables: $ result.1: Factor w/ 2 levels "1","2": 1 1 2 2 $ result.2: Factor w/ 2 levels "2","3": 1 1 2 2 中有一个包可以让我这样做吗?

{{1}}

1 个答案:

答案 0 :(得分:4)

首先,您必须知道R(通常)call by value,所以无论您做什么,您最终都会得到数据框的临时副本。这适用于apply系列的正常版本。一旦你在函数内部更改了某些内容,就会先复制该对象。

这就是说,mclapply不会将完整的工作区内容复制到子进程。据我所知,进程共享相同的内存内容,只有在对内容进行修改后才复制内容。无论如何,R或多或少都会降低。

如果您仍然不相信这一点,可以使用群集方法并尝试parLapplyparallel包中的朋友。这不是基于分叉,而是基于节点集群。您可以在此处将核心视为节点。在这种情况下,您必须使用clusterExport()从计算所需的工作空间中显式导出变量。我不确定这一点,但我怀疑这确实创造了一个副本。对于其余部分,parLapply仅将其处理的元素复制到不同的集群。同样,这与lapply默认执行的操作相同。

使用您的数据框a,您可以执行以下操作:

> require(parallel)
> cl <- makeCluster(2)
> b <- parLapply(cl,a,as.factor)
> str(as.data.frame(b))
'data.frame':   4 obs. of  2 variables:
 $ b: Factor w/ 2 levels "1","2": 1 1 2 2
 $ c: Factor w/ 2 levels "2","3": 1 1 2 2
> stopCluster(cl)