2016-07-25 9 views
0

Unten finden Sie ein Stück Code in R, die ich konvertieren möchte, um als paralleler Prozess mit mehreren CPUs zu laufen. Ich versuchte mit foreach Paket, aber ging nicht weit .. Ich konnte kein gutes Beispiel finden, wie es funktioniert angesichts der Tatsache, dass ich 3-Level Nested Loop haben. Hilfe wäre sehr willkommen. Beispiel für Code unten - Ich habe eine einfache Funktion, so dass es als Beispiel dienen kann:Konvertierung von verschachtelten for-loop zu parallel in R

celnum <- c(10,20,30) 
t2 <- c(1,2,3) 
allrepeat <- 10 

samplefunction <- function(celnum,t2){ 

     x <- rnorm(100,celnum,t2) 
     y = sample(x, 1) 
     z = sample(x,1) 

     result = y+z 


     result 
} 

Erste Ergebnisse herkömmliche Art und Weise:

z_grid <- matrix(, nrow = length(celnum), ncol = length(t2)) 

repetitions <- matrix(, nrow = allrepeat, ncol = 1) 



set.seed=20 
for(i in 1:length(celnum)){ 
     for (j in 1:length(t2)){ 
       for (k in 1:allrepeat) { 
         results <- samplefunction(celnum[i],t2[j]) 
           repetitions[k] <- results 
           z_grid[i,j] <- mean(repetitions,na.rm=TRUE) 
       } 
     } 
} 

z_grid 

nun versucht, das gleiche mit foreach zu tun:

set.seed=20 

library(foreach) 
library(doSNOW) 

cl <- makeCluster(3, type = "SOCK") 
registerDoSNOW(cl) 

set.seed=20 
output <- foreach(i=1:length(celnum),.combine='cbind') %:% 
     foreach (j=1:length(t2), .combine='c') %:% 
       foreach (k = 1:allrepeat) %do% { 
         mean(samplefunction(celnum[i],t2[j])) 
} 
output 

Dies funktioniert nicht so, wie ich es möchte, da es eine Matrix von 30x2 Dimensionen statt 3x3 zurückgibt. Meine Absicht ist es, das Szenario für i- und j-Kombinationen k-mal zu simulieren und möchte einen Durchschnitt dieser k-Simulationen für jede Kombination von i und j erhalten.

+2

vielleicht werfen Sie einen Blick auf die [Dokumentation] (http://stackoverflow.com/documentation/r/1677/parallel-processing/5164/parallel-processing-with-foreach-package#t=201607251334159676214) – loki

+0

@ Loki: Danke das ist sehr gut. Ich kann eine einfache Schleife mit foreach ausführen.Ich habe jedoch eine schwierige Zeit, dieses Stück Code zu konvertieren, der mir eine Ausgabe einer Liste von vier Matrizen als Ergebnis gibt, und wo es eine geschachtelte 3-Level-Schleife gibt, um die Funktion auszuführen. Ich bin immer noch auf einer steilen Lernkurve mit R – MIH

Antwort

2

EDIT:

Die verschachtelte for-Schleifen sollte wie folgt aussehen. Beachten Sie, dass nur eine foreach und zwei for Schleifen verschachtelt sind.

library(foreach) 
library(doSNOW) 

cl <- makeCluster(3, type = "SOCK") 
registerDoSNOW(cl) 

set.seed(20) 
output <- foreach(k=1:allrepeat) %dopar% { 
    df <- data.frame() 
    for (i in 1:length(t2)) { 
    for (j in 1:length(celnum)) { 
     df[i,j] <- mean(samplefunction(celnum[i],t2[j])) 
    } 
    } 
    df 
} 

Das Ergebnis output ist auch ein list. Um die Zelle zu berechnen bedeutet this post viel geholfen.

library(plyr) 
aaply(laply(output, as.matrix), c(2,3), mean) 

# X2 
# X1  V1  V2  V3 
# 1 20.30548 21.38818 18.49324 
# 2 40.09506 40.64564 40.34847 
# 3 60.10946 59.68913 58.66209 

btw: Sie sollten ...

stopCluster(cl) 

... danach.


Original-Beitrag:

Zuerst müssen Sie bestimmen, welche der for Schleifen Sie mit der foreach Schleife ersetzt werden soll.

Grundsätzlich wird diese Entscheidung hauptsächlich durch die Ergebnisse der Schleife beeinflusst und somit, wie diese Ergebnisse kombiniert werden können. Da Sie einzelne Prozesse an die einzelnen Prozessoren Ihres PCs auslagern, wird nur das letzte Element zurückgegeben. Diese Ergebnisse werden kombiniert, wie in dem Parameter .combine angegeben (z. B. 'c', 'cbind' usw.). Da Sie versuchen, zwei Listen zu generieren, könnte dies wahrscheinlich nicht sehr einfach für einen ersten Start sein. Daher möchte ich ein Beispiel vorschlagen, das die Funktionalität der foreach-Schleife beschreibt, die innerhalb anderer for-Schleifen verschachtelt ist.

library(foreach) 
library(doSNOW) 

dat1 <- c(15.2, 12.58, 4.25, 1.05, 6.78, 9.22, 11.20) 
dat2 <- data.frame(matrix(1:15, ncol = 3)) 


cl <- makeCluster(3, type = "SOCK") 
registerDoSNOW(cl) 

for (i in 1:nrow(dat2)) { 
    FEresult <- foreach(j = 1:ncol(dat2), .combine = c, .inorder = TRUE) %dopar% { 
    tmp <- dat1 * dat2[i, j] 
    data.frame(tmp) 
    } 
    FEresult 
    if (i == 1) { 
    res <- FEresult 
    } else { 
    res <- rbind(res, FEresult) 
    } 
} 

res 

Sie werden feststellen, dass das Ergebnis dieser Schleife eine Liste ist.

+0

Danke. Ich entschied mich, die Funktion etwas zu vereinfachen (siehe editierten Beitrag). Macht es Ihnen etwas aus, einen Blick darauf zu werfen und zu sehen, welche finale Optimierung Ihnen dabei helfen wird? – MIH

+0

wenn ich die Schleife kopiere, funktioniert es. vielleicht editierst du die Fehlermeldung in deine Frage, damit ich sie mir ansehen kann – loki

+0

Es gibt keine Fehlermeldung aber die Ergebnisse sind nicht wie gewünscht. Ich möchte die gleichen Ergebnisse in "Ausgabe" wie in "z_grid" erhalten. Die erste ist eine [3,3] -Matrix von [i, j], wobei k Simulationen dieser Matrix als Mittelwert in jedem Matrixeintrag summiert werden. Macht es Sinn? Mit anderen Worten, ich simuliere das Szenario für i- und j-Kombinationen k-mal und möchte für jede Kombination von i und j einen Mittelwert dieser k-Simulationen erhalten. Die aktuelle Ausgabe mit 'foreach' gibt mir 30x3 Ausgabedimension und ich bin mir nicht einmal sicher, wie genau sie bestellt sind. – MIH