2015-02-24 1 views
1

Я пытаюсь распараллелить цикл for, который у меня есть. Внутри рассматриваемого цикла есть вложенный цикл, который я хотел бы распараллелить. Ответ должен быть очень похож на: nested foreach loops in R to update common array, но я не могу заставить его работать. Я пробовал все варианты, о которых я могу думать, включая просто превращение внутреннего цикла в его собственную функцию и распараллеливание этого, но я продолжаю получать пустые списки.Вложенный цикл foreach в R, где внутренний цикл возвращает матрицу

Первый, не Еогеасп пример работы:

theFrame <- data.frame(col1=rnorm(100), col2=rnorm(100)) 

theVector <- 2:30 

regFor <- function(dataFrame, aVector, iterations) 
{ 
    #set up a blank results matrix to save into. 
    results <- matrix(nrow=iterations, ncol=length(aVector)) 

    for(i in 1:iterations) 
    { 
     #set up a blank road map to fill with 1s according to desired parameters 
     roadMap <- matrix(ncol=dim(dataFrame)[1], nrow=length(aVector), 0) 
     row.names(roadMap) <- aVector 
     colnames(roadMap) <- 1:dim(dataFrame)[1] 

     for(j in 1:length(aVector)) 
     { 
      #sample some of the 0s and convert to 1s according to desired number of sample 
      roadMap[j,][sample(colnames(roadMap),aVector[j])] <- 1 
     } 

     temp <- apply(roadMap, 1, sum) 

     results[i,] <- temp 
    } 

    results <- as.data.frame(results) 
    names(results) <- aVector 

    results 
} 

test <- regFor(theFrame, theVector, 2) 

Но это и другие мои подобные попытки не работают.

trying <- function(dataFrame, aVector, iterations, cores) 
{ 
    registerDoMC(cores) 

    #set up a blank results list to save into. i doubt i need to do this 
    results <- list() 

    foreach(i = 1:iterations, .combine="rbind") %dopar% 
    { 
     #set up a blank road map to fill with 1s according to desired parameters 
     roadMap <- matrix(ncol=dim(dataFrame)[1], nrow=length(aVector), 0) 
     row.names(roadMap) <- aVector 
     colnames(roadMap) <- 1:dim(dataFrame)[1] 

     foreach(j = 1:length(aVector)) %do% 
     { 
      #sample some of the 0s and convert to 1s according to desired number of sample 
      roadMap[j,][sample(colnames(roadMap),aVector[j])] <- 1 
     } 

     results[[i]] <- apply(roadMap, 1, sum) 
    } 
    results 
} 

test2 <- trying(theFrame, theVector, 2, 2) 

Я полагаю, что я должен использовать foreach во внутренней петле независимо от того, что, правильно?

ответ

4

При использовании Еогеаспа, вы никогда не «создать пустой список результатов, чтобы сохранить в», как вы подозревали. Вместо этого вы комбинируете результаты оценки тела цикла foreach, и этот комбинированный результат возвращается. В этом случае мы хотим, чтобы внешняя петля foreach объединяла векторы (вычисляемые внутренним циклом foreach) по ряду строк в матрицу. Эта матрица назначается переменной results, которая затем преобразуется в кадр данных.

Вот моя первая попытка преобразовать ваш пример:

library(doMC) 

foreachVersion <- function(dataFrame, aVector, iterations, cores) { 
    registerDoMC(cores) # unusual, but reasonable with doMC 
    rows <- nrow(dataFrame) 
    cols <- length(aVector) 
    results <- 
    foreach(i=1:iterations, .combine='rbind') %dopar% { 
     # The value of the inner foreach loop is returned as 
     # the value of the body of the outer foreach loop 
     foreach(aElem=aVector, .combine='c') %do% { 
     roadMapRow <- double(length=rows) 
     roadMapRow[sample(rows,aElem)] <- 1 
     sum(roadMapRow) 
     }  
    } 
    results <- as.data.frame(results) 
    names(results) <- aVector 
    results 
} 

Внутренний цикл не должен быть реализован в виде цикла Еогеасп. Вы также можете использовать sapply, но я попытаюсь выяснить, есть ли более быстрый метод. Но для этого ответа я хотел продемонстрировать метод foreach. Единственная реальная оптимизация, которую я использовал, заключалась в том, чтобы избавиться от вызова до apply, выполнив sum внутри внутреннего цикла foreach.

+0

Спасибо! Это хорошо работает. В случае, если это было непонятно, мой фактический код делает более сложные вещи внутри обеих петель, поэтому использование sapply и т. Д. Может быть довольно сложным. В моей первоначальной формулировке были две основные проблемы. Первый - это создание пустого списка и попытка сохранить в нем результаты (кстати, я успешно это сделал с foreach в других обстоятельствах), а второй не понял смысла того, что делает .combine. Это классно и дает результаты без использования таких вещей, как Reduce(), которые я делал в прошлом с foreach. Благодаря! – forlooper

+0

@forlooper Возможно, есть побочные эффекты в петлях foreach, но он работает по-разному в зависимости от того, какой бэкэнд вы используете, поэтому его сильно обескураживают. Я изначально пытался предотвратить возможность побочных эффектов в foreach, но я в конце концов отказался от попыток. –

+0

Спасибо Стив. Я думаю, что я должен перепрограммировать некоторые вещи тогда! – forlooper

3

Вам нужно поместить результат в Еогеаспе в переменном:

results<- foreach(... 
+0

Это была основная проблема. Благодаря! Ответ Стива Уэстона выше - это полный ответ на эту проблему. – forlooper

+0

Тогда отметьте его ответ как ваш ответ и, пожалуйста, проголосуйте. – cmbarbu

+0

Извините, я нажал на неправильные символы при первом просмотре. Я исправил это сейчас. Еще раз спасибо. – forlooper