2011-08-17 38 views
2

我有需要進入「並行化」階段的R代碼。如果我使用錯誤的條款,請原諒我。我有一個過程,只需逐個地逐個挑選個人,然後平均分配給個人。這個過程對每個人來說都是一樣的(它是一座布朗橋),我只需要爲> 300個人做這件事。所以,我希望這裏有人可能知道如何改變我的代碼,以便它可以被派生出來?或並行?或者無論這個詞是什麼,以確保我現在可以訪問的48個CPU可以幫助減少58天,這將用我的小筆記本電腦來計算。在我的腦海中,我只會發送一個人到一個處理器。讓它通過腳本運行,然後發送另一個....如果這是有道理的。如何重寫我的R代碼以進行多核處理?

以下是我的代碼。我試圖在其中發表評論,並指出我認爲代碼需要更改的地方。

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

我不知道有人投了-1,但我懷疑是因爲你的代碼太複雜 - 它需要很長時間才能篩選出來。你能給我們一個只有10-20行長的簡化版本,還有完整的R語法,但是能給出你想要做什麼的想法?另外,你能否告訴我們更多關於你的計算機設置 - 多核,緊密耦合的機器,......?你有什麼想法(請參閱http://cran.r-project.org/web/views/HighPerformanceComputing.html上的高性能任務視圖) –

+0

Seconding Brian。不要讓我們做你所有的工作。只需向我們展示您需要進行並行處理的步驟,我們就可以爲您提供幫助。 – Maiasaura

+0

哎呀,我打算輸入Ben。抱歉! – Maiasaura

回答

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)} 
) 

很難說這是否是它沒有一些測試數據,讓我知道你上車。

+0

@nezcoops - 啊你有很多信仰我的兄弟認爲我得到了正確的skillzzz!謝謝。使用其他人的腳本和例子來產生目前所得到的一直是一場鬥爭。但是,我會堅持下去。我從來沒有使用過lapply命令,這是第一次聽到這個習慣。 – Kerry

+0

擴展了答案,因爲我在註釋字段中空間不足。 – nzcoops

4

這是一個普遍的例子,因爲我沒有耐心閱讀所有的代碼。在多個處理器之間傳播這種信息最快捷的方法之一是使用multicore庫和mclapplylapply的並行版本)來推送一個列表(列表中的單個項目將是您的300多個人中的每一個人的數據框案例)通過一個函數。

例子:

library(multicore) 
result=mclapply(data_list, your_function,mc.preschedule=FALSE, mc.set.seed=FALSE) 
+0

感謝您的建議,我已將代碼縮減到我認爲可解析到各種處理器的部分。代碼中只有1個主要功能(brownian.bridge命令)。這是我的數據集中每個人需要計算的數據。我從IF語句開始的地方就是將結果和綁定到Grid中的地方。我認爲發送到集羣是不必要的,但我不明白該進程如何知道從所有不同的處理器返回並聯合在一起。 – Kerry

+1

R.在For循環中效率低下。使用plyr將每個人的數據放入列表中。例如:個人= dlply(original_data,。(IDNames))。接下來,創建一個包裝函數(一次向該函數傳遞一個列表項),該函數包含bbbm函數和格式化結果。因此,當多核運行時,它將執行這兩個操作並返回一個列表,其中各個項目是綁定到網格的結果。然後你可以做任何事情(例如摺疊列表,繪圖)等等。 – Maiasaura

2

據我瞭解你的描述,你可以訪問分佈式計算機集羣。所以包多核將無法正常工作。你必須使用Rmpi,snow或者foreach。基於你現有的循環結構,我會建議使用foreach和doSnow軟件包。但是你的代碼看起來像你有很多數據。您可能需要檢查以減少將發送到節點的數據(僅限於所需的數據)。

相關問題