3

我有一个for循环,它生成 viapng()dev.off()一个绘图并将其保存到工作目录。

我拥有的循环类似于以下示例

test.df<-data.frame(id=1:25000, x=rnorm(25000),y=rnorm(25000))

for (i in test.df$id){
  plot(test.df$x[test.df$id==i], test.df$y[test.df$id==i], xlab="chi",ylab="psi")
}

循环将for运行并生成数千个图。是否可以让它在我系统的所有 8 个内核上并行运行,以便我可以更快地获得绘图?

PS。代码是一个例子。我原来的问题和情节要复杂得多。不要在示例中传播病毒。

4

3 回答 3

6

如果您使用的是新版本的 R,那么这应该很简单。诀窍是创建一个可以以任何顺序在任何核心上运行的函数。首先我们创建我们的数据框:

test.df = data.frame(id=1:250, x=rnorm(250),y=rnorm(250))

接下来我们创建在每个核心上运行的函数:

#I could also pass the row or the entire data frame
myplot = function(id) {
  fname = paste0("/tmp/plot", id, ".png")
  png(fname)
  plot(test.df$x[id], test.df$y[id], 
      xlab="chi",ylab="psi")
  dev.off()
  return(fname)
}

然后我加载parallel包(这带有base R)

library(parallel)

然后使用mclapply

no_of_cores = 8
##Non windows
mclapply(1:nrow(test.df), myplot, 
         mc.cores = no_of_cores)

##All OS's
cl = makeCluster(no_of_cores)
clusterExport(cl, "test.df")
parSapply(cl, 1:nrow(test.df), myplot)
stopCluster(cl)

这里有两个优点:

  1. parallel自带R,所以我们不需要安装任何额外的东西
  2. 我们可以关闭“并行”部分:

    sapply(1:nrow(test.df), myplot)
    
于 2013-01-27T19:19:05.170 回答
5

使用foreach包,您必须最低限度地修改您的核心代码。此外,您还可以选择有关操作系统或其他问题的任何后端。

##
## Working dir and data generation
##
setwd("/path/to")
N <- 25000
test.df<-data.frame(id=1:N, x=rnorm(N),y=rnorm(N))

##
## Making a cluster
##
require(doSNOW) # Or any other backend of your choice
NC <- 8         # Number of nodes in cluster, i.e. cores
cl <- makeCluster(rep("localhost", NC), type="SOCK")
registerDoSNOW(cl)

## 
## Core loop
##
foreach(i=1:N) %dopar% {
  png(paste("plot",i,".png",sep=""))
  plot(test.df$x[test.df$id==i], test.df$y[test.df$id==i], xlab="chi",ylab="psi")
  dev.off()
}

##
## Stop cluster
##
stopCluster(cl)

选择一个核心很容易:只需替换%dopar%%do%.

于 2013-01-27T19:20:08.650 回答
3

由于mclapplywindows不支持,所以我为windows用户提供了一个解决方案,使用parallel包。

cl <- makeCluster(8)
parSapply(cl, 1:20, fun, fun.args)
于 2013-01-27T19:41:00.213 回答