2

我有需要进入“并行化”阶段的 R 代码。我是新手,所以如果我使用了错误的术语,请原谅我。我有一个过程,只需要一次一个地遍历一个人,然后最终在各个人之间进行平均。这个过程对于每个人来说都是完全相同的(它是一个布朗桥),我只需要为超过 300 个人做这个。所以,我希望这里有人可能知道如何更改我的代码以便生成它?或并行化?或者不管用什么词来确保我现在可以使用的 48 个 CPU 可以帮助减少用我的小笔记本电脑计算这个所需的 58 天。在我的脑海中,我只会将 1 个人发送到一个处理器。让它通过脚本运行,然后发送另一个....如果有意义的话。

下面是我的代码。我试图在其中发表评论,并指出我认为代码需要更改的地方。

for (n in 1:(length(IDNames))){ #THIS PROCESSES THROUGH EACH INDIVIDUAL 

#THIS FIRST PART IS JUST EXTRACTING THE DATA FROM MY TWO INPUT FILES.  
#I HAVE ONE FILE WITH ALL THE LOCATIONS AND THEN ANOTHER FILE WITH A DATE RANGE.  
#EACH INDIVIDUAL HAS DIFFERENT DATE RANGES, THUS IT HAS TO PULL OUT EACH INDIVIDUALS 
#DATA SET SEPARATELY AND THEN RUN THE FUNCTION ON IT.

    IndivData = MovData[MovData$ID==IDNames[n],]
    IndivData = IndivData[1:(nrow(IndivData)-1),]
    if (UseTimeWindow==T){
      IndivDates = dates[dates$ID==IDNames[n],]
      IndivData = IndivData[IndivData$DateTime>IndivDates$Start[1]&IndivData$DateTime<IndivDates$End[1],]
    }
    IndivData$TimeDif[nrow(IndivData)]=NA

    ########################
#THIS IS THE PROCESS WHERE I THINK I NEED THAT HAS TO HAVE EACH INDIVIDUAL RUN THROUGH IT

    BBMM <- brownian.bridge(x=IndivData$x, y=IndivData$y,
    time.lag = IndivData$TimeDif[1:(nrow(IndivData)-1)], location.error=20,
    area.grid = Grid, time.step = 0.1)

  #############################
  # BELOW IS JUST CODE TO BIND THE RESULTS INTO A GRID DATA FRAME I ALREADY CREATED.  
  #I DO NOT UNDERSTAND HOW THE MULTICORE PROCESSED CODE WOULD JOIN THE DATA BACK 
  #WHICH IS WHY IVE INCLUDED THIS PART OF THE CODE.  

    if(n==1){   #creating a data fram with the x, y, and probabilities for the first individual
      BBMMProbGrid = as.data.frame(1:length(BBMM[[2]]))
      BBMMProbGrid = cbind(BBMMProbGrid,BBMM[[2]],BBMM[[3]],BBMM[[4]])
      colnames(BBMMProbGrid)=c("GrdId","X","Y",paste(IDNames[n],"_Prob", sep=""))
    } else {                #For every other individual just add the new information to the dataframe
      BBMMProbGrid = cbind(BBMMProbGrid,BBMM[[4]])
      colnames(BBMMProbGrid)[n*2+2]=paste(IDNames[n],"_Prob", sep ="")
    }# end if  


    } #end loop through individuals
4

3 回答 3

4

不知道为什么这也被否决了。我认为foreach包是你所追求的。前几个 pdf 中包含非常清晰的有用信息。基本上把你想为每个人做的事情写成一个函数。然后使用 foreach 将一个人的数据发送到一个节点以运行该函数(同时将另一个人发送到另一个节点等),然后它使用 rbind 之类的东西编译所有结果。我已经使用了几次,效果很好。

编辑:我不打算修改你的代码,因为我认为你已经做到了这么远,你很容易掌握将它包装到一个函数中然后使用一个衬垫 foreach 的技能。

编辑 2:评论太长,无法回复您。

我想既然你已经掌握了这么多的代码,你就可以把它变成一个函数:)如果你还在做这个,考虑写一个 for 循环来循环你的主题并做可能会有所帮助该科目所需的计算。然后,那个 for 循环就是你想要的函数。我认为在您的代码中,一切都归结为“area.grid”。然后你可以摆脱你的大部分 [n],因为数据每次迭代只有一次子集。

也许:

pernode <- function(MovData) {
    IndivData = MovData[MovData$ID==IDNames[i],]
    IndivData = IndivData[1:(nrow(IndivData)-1),]
    if (UseTimeWindow==T){
                         IndivDates = dates[dates$ID==IDNames,]
                         IndivData = IndivData[IndivData$DateTime>IndivDates$Start[1]
                         &IndivData$DateTime<IndivDates$End[1],]
                         }
    IndivData$TimeDif[nrow(IndivData)]=NA

    BBMM <- brownian.bridge(x=IndivData$x, y=IndivData$y,
    time.lag = IndivData$TimeDif[1:(nrow(IndivData)-1)], location.error=20,
    area.grid = Grid, time.step = 0.1)

return(BBMM)
}

然后是这样的:

library(doMC)
library(foreach)
registerDoMC(cores=48) # or perhaps a few less than all you have

system.time(
  output <- foreach(i = 1:length(IDNames)), .combine = "rbind", .multicombine=T,
 .inorder = FALSE) %dopar% {pernode(i)}
)

很难说没有一些测试数据是否是这样,让我知道你的进展情况。

于 2011-08-17T02:01:13.647 回答
4

这是一个通用示例,因为我没有耐心阅读您的所有代码。将其传播到多个处理器的最快方法之一是使用multicore库和mclapply(的并行版本lapply)推送列表(列表中的单个项目将是您的案例中 300 多个个人中的每个人的数据框)通过一个函数。

例子:

library(multicore)
result=mclapply(data_list, your_function,mc.preschedule=FALSE, mc.set.seed=FALSE)
于 2011-08-17T02:25:11.597 回答
2

据我了解,您可以访问分布式计算机集群。所以包 multicore 将无法正常工作。你必须使用 Rmpi​​、snow 或 foreach。根据您现有的循环结构,我建议使用 foreach 和 doSnow 包。但是你的代码看起来像你有很多数据。您可能必须检查以减少将发送到节点的数据(仅需要的数据)。

于 2011-08-17T09:57:01.477 回答