2014-09-04 122 views
1

跑我有這樣的循環:代for循環中並行R中

library(EnvStats) 
mvfyfueu <- matrix(, nrow = 0, ncol = 3) 
for (i in 1:2000) { 

    # fy (S355, yield strength N/mm2) 
    meanmean = 419.38 #(*) 
    sdmean = 10 #(**) 
    meanmeanlv = 400 #(**) 
    meanmeanuv = 440 #(**) 
    meanfy <- dist(meanmean,sdmean,meanmeanlv,meanmeanuv,"norm") 

    meansd = 20.25 #(*) 
    sdsd = 5 #(**) 
    meansdlv = 15 #(**) 
    meansduv = 25 #(**) 
    sdfy <- dist(meansd,sdsd,meansdlv,meansduv,"norm") 

    fylv = 355 #(*) 
    fyuv = 500 #(**) 
    lsupfy <- 1 - plnormTruncAlt(fyuv, mean = meanfy[1], cv = sdfy[1]/meanfy[1]) - 1e-10 
    linffy <- plnormTruncAlt(fylv, mean = meanfy[1], cv = sdfy[1]/meanfy[1]) - 1e-10 

    # fu (S355, tensile strength N/mm2) 
    meanmean = 533.44 #(*) 
    sdmean = 10 #(**) 
    meanmeanlv = 500 #(**) 
    meanmeanuv = 550 #(**) 
    meanfu <- dist(meanmean,sdmean,meanmeanlv,meanmeanuv,"norm") 

    meansd = 16.53 #(*) 
    sdsd = 5 #(**) 
    meansdlv = 10 #(**) 
    meansduv = 25 #(**) 
    sdfu <- dist(meansd,sdsd,meansdlv,meansduv,"norm") 

    fulv = 470 #(*) 
    fuuv = 630 #(*) 
    lsupfu <- 1 - plnormTruncAlt(fuuv, mean = meanfu[1], cv = sdfu[1]/meanfu[1]) - 1e-10 
    linffu <- plnormTruncAlt(fulv, mean = meanfu[1], cv = sdfu[1]/meanfu[1]) - 1e-10 

    # eu (S355, strain at maximum strength mm/mm) 
    meanmean = 0.2645 #(*) 
    sdmean = 10 #(**) 
    meanmeanlv = 0.2 #(**) 
    meanmeanuv = 0.3 #(**) 
    meaneu <- dist(meanmean,sdmean,meanmeanlv,meanmeanuv,"norm") 

    meansd = 0.0613 #(*) 
    sdsd = 0.02 #(**) 
    meansdlv = 0.02 #(**) 
    meansduv = 0.1 #(**) 
    sdeu <- dist(meansd,sdsd,meansdlv,meansduv,"norm") 

    eulv = 0.1 #(*) 
    euuv = 0.3 #(*) 
    lsupeu <- 1 - plnormTruncAlt(euuv, mean = meaneu[1], cv = sdeu[1]/meaneu[1]) - 1e-10 
    linfeu <- plnormTruncAlt(eulv, mean = meaneu[1], cv = sdeu[1]/meaneu[1]) - 1e-10 

    #Generate samples 
    mat.fyfueu <- simulateMvMatrix(2000, 
           distributions = c(fy = "lnormAlt",fu = "lnormAlt",eu = "lnormAlt"), 
           param.list = list(fy = list(mean=meanfy[1], cv=sdfy[1]/meanfy[1]), 
               fu = list(mean=meanfu[1], cv=sdfu[1]/meanfu[1]), 
               eu = list(mean=meaneu[1], cv=sdeu[1]/meaneu[1])), 
           left.tail.cutoff = c(fy = ifelse(linffy <= 1e-5, 0, linffy), 
                 fu = ifelse(linffu <= 1e-5, 0, linffu), 
                 eu = ifelse(linfeu <= 1e-5, 0, linfeu)), 
           right.tail.cutoff = c(fy = ifelse(lsupfy <= 0, .Machine$double.eps, lsupfy), 
                 fu = ifelse(lsupfu <= 0, .Machine$double.eps, lsupfu), 
                 eu = ifelse(lsupeu <= 0, .Machine$double.eps, lsupeu)), 
           cor.mat = matrix(c(1, .75, -0.45, .75, 1, -0.6, -0.45, -0.6, 1), 3, 3), 
           sample.method = "LHS", max.iter = 100) #, seed = i 

    mvfyfueu <- rbind2(mvfyfueu, mat.fyfueu) 
} 

DIST功能:

dist <- function(meanv, sdv, lv, uv, dist) { 
    library(EnvStats) 
    lsup <- 1 - pnorm(uv, mean = meanv, sd = sdv) 
    linf <- pnorm(lv, mean = meanv, sd = sdv) 
    value <- simulateVector(2, distribution = dist, 
         param.list = list(mean = meanv, sd = sdv), #seed = i, 
         sort = FALSE, left.tail.cutoff = ifelse(linf == 0, .Machine$double.eps, linf), 
         right.tail.cutoff = ifelse(lsup == 0, .Machine$double.eps, lsup), sample.method = "LHS") 
    return(value) 
} 

現在我想運行在平行,所以我將其更改爲:

library(doParallel) 
library(foreach) 
#setup parallel backend to use 7 processors 
cl<-makeCluster(7) 
registerDoParallel(cl) 
library(EnvStats) 
mvfyfueu <- matrix(, nrow = 0, ncol = 3) 
iters <- 100 
foreach(icount(iters)) %dopar% { 

    # fy (S355, yield strength N/mm2) 
    meanmean = 419.38 #(*) 
    sdmean = 10 #(**) 
    meanmeanlv = 400 #(**) 
    meanmeanuv = 440 #(**) 
    meanfy <- dist(meanmean,sdmean,meanmeanlv,meanmeanuv,"norm") 

    meansd = 20.25 #(*) 
    sdsd = 5 #(**) 
    meansdlv = 15 #(**) 
    meansduv = 25 #(**) 
    sdfy <- dist(meansd,sdsd,meansdlv,meansduv,"norm") 

    fylv = 355 #(*) 
    fyuv = 500 #(**) 
    lsupfy <- 1 - plnormTruncAlt(fyuv, mean = meanfy[1], cv = sdfy[1]/meanfy[1]) - 1e-10 
    linffy <- plnormTruncAlt(fylv, mean = meanfy[1], cv = sdfy[1]/meanfy[1]) - 1e-10 

    # fu (S355, tensile strength N/mm2) 
    meanmean = 533.44 #(*) 
    sdmean = 10 #(**) 
    meanmeanlv = 500 #(**) 
    meanmeanuv = 550 #(**) 
    meanfu <- dist(meanmean,sdmean,meanmeanlv,meanmeanuv,"norm") 

    meansd = 16.53 #(*) 
    sdsd = 5 #(**) 
    meansdlv = 10 #(**) 
    meansduv = 25 #(**) 
    sdfu <- dist(meansd,sdsd,meansdlv,meansduv,"norm") 

    fulv = 470 #(*) 
    fuuv = 630 #(*) 
    lsupfu <- 1 - plnormTruncAlt(fuuv, mean = meanfu[1], cv = sdfu[1]/meanfu[1]) - 1e-10 
    linffu <- plnormTruncAlt(fulv, mean = meanfu[1], cv = sdfu[1]/meanfu[1]) - 1e-10 

    # eu (S355, strain at maximum strength mm/mm) 
    meanmean = 0.2645 #(*) 
    sdmean = 10 #(**) 
    meanmeanlv = 0.2 #(**) 
    meanmeanuv = 0.3 #(**) 
    meaneu <- dist(meanmean,sdmean,meanmeanlv,meanmeanuv,"norm") 

    meansd = 0.0613 #(*) 
    sdsd = 0.02 #(**) 
    meansdlv = 0.02 #(**) 
    meansduv = 0.1 #(**) 
    sdeu <- dist(meansd,sdsd,meansdlv,meansduv,"norm") 

    eulv = 0.1 #(*) 
    euuv = 0.3 #(*) 
    lsupeu <- 1 - plnormTruncAlt(euuv, mean = meaneu[1], cv = sdeu[1]/meaneu[1]) - 1e-10 
    linfeu <- plnormTruncAlt(eulv, mean = meaneu[1], cv = sdeu[1]/meaneu[1]) - 1e-10 

    #Generate samples 
    mat.fyfueu <- simulateMvMatrix(2000, 
           distributions = c(fy = "lnormAlt",fu = "lnormAlt",eu = "lnormAlt"), 
           param.list = list(fy = list(mean=meanfy[1], cv=sdfy[1]/meanfy[1]), 
                fu = list(mean=meanfu[1], cv=sdfu[1]/meanfu[1]), 
                eu = list(mean=meaneu[1], cv=sdeu[1]/meaneu[1])), 
           left.tail.cutoff = c(fy = ifelse(linffy <= 1e-5, 0, linffy), 
                 fu = ifelse(linffu <= 1e-5, 0, linffu), 
                 eu = ifelse(linfeu <= 1e-5, 0, linfeu)), 
           right.tail.cutoff = c(fy = ifelse(lsupfy <= 0, .Machine$double.eps, lsupfy), 
                 fu = ifelse(lsupfu <= 0, .Machine$double.eps, lsupfu), 
                 eu = ifelse(lsupeu <= 0, .Machine$double.eps, lsupeu)), 
           cor.mat = matrix(c(1, .75, -0.45, .75, 1, -0.6, -0.45, -0.6, 1), 3, 3), 
           sample.method = "LHS", max.iter = 100) #, seed = i 

    mvfyfueu <- rbind2(mvfyfueu, mat.fyfueu) 
} 

但在平行運行結束時,我得到一個空的mvfyfueu矩陣:

> mvfyfueu 
    [,1] [,2] [,3] 

這與串行運行的結果完全不同。我應該糾正什麼?謝謝

+1

嘗試在當前'for_each'主體的最後一行之後使用隱式返回,即'mvfyfueu'將是您在主體中的最後一行;並將'for_each'調用分配給名爲'mvfyfueu'的對象 - ''mvfyfueu < - for_each(...)%dopar%{...}'。我認爲這應該解決這個問題。 – nrussell 2014-09-04 17:36:26

+0

這使'mvfyfueu'成爲一個列表,在每次迭代中將新列添加到列表中。我想要的是在每個迭代中創建新行的矩陣。但它改善了結果。謝謝! – jpcgandre 2014-09-04 17:45:49

+2

你有一個TON的靜態變量在那裏!嘗試給他們一個獨特的名字,或者將它們組合成一個向量,然後將這個向量提供給你的函數。這將比每次循環重新定義它們要快得多。 – 2014-09-04 18:12:16

回答

2

因爲我沒有一套合適的對象來測試你的功能,或者創建一個可比較版本的腳本的時間,我只會用一些玩具數據和一個微不足道的過程來演示 -

library(iterators) 
library(foreach) 
## your parallel backend setup may 
## be different, but that shouldn't 
## affect anything 
library(doSNOW) 
library(parallel) 
## 
mvfyfueu <- matrix(, nrow = 0, ncol = 3) 
iters <- 100 
v1 <- v2 <- v3 <- 1:100 
## 
cl <- parallel::makeCluster("SOCK",3) 
registerDoSNOW(cl) 
## 
mvfyfueu <- foreach(
    icount(iters), 
    .combine=rbind) %dopar% { 

    mat_row <- matrix(
     c(sample(v1), 
     sample(v2), 
     sample(v3)), 
     nrow=1, 
     ncol=3, 
     byrow=TRUE) 
    mat_row 
    } 
## 
stopCluster(cl) 
## 
> dim(mvfyfueu) 
[1] 100 3 
> head(mvfyfueu) 
    [,1] [,2] [,3] 
[1,] 80 95 77 
[2,] 75 24 57 
[3,] 33 89 67 
[4,] 29 91 75 
[5,] 18 75 20 
[6,] 54 44 25 

當您使用foreach你最應該採取的.combine參數,它決定了你的數據是如何結合的優勢(在我的經驗,這通常是rbind)。當你這樣做時,你不需要在每個迭代中用foreach正文中的全局對象明確地rbind對象,.combine參數處理這個問題。正如我在評論中指出的那樣,我認爲有必要將foreach調用分配給對象。讓我知道這是否有幫助,如果沒有,請隨時發佈一些示例數據以測試您的代碼。