2014-01-23 94 views
4

我熟悉foreach%dopar%等。我也熟悉parallel選項cv.glmnet。但你如何設置嵌套parallelistion如下?嵌套並行功能

library(glmnet) 
library(foreach) 
library(parallel) 
library(doSNOW) 
Npar <- 1000 
Nobs <- 200 
Xdat <- matrix(rnorm(Nobs * Npar), ncol = Npar) 
Xclass <- rep(1:2, each = Nobs/2) 
Ydat <- rnorm(Nobs) 

並行交叉驗證:

cl <- makeCluster(8, type = "SOCK") 
registerDoSNOW(cl) 
system.time(mods <- foreach(x = 1:2, .packages = "glmnet") %dopar% { 
    idx <- Xclass == x 
    cv.glmnet(Xdat[idx,], Ydat[idx], nfolds = 4, parallel = TRUE) 
}) 
stopCluster(cl) 

不平行交叉驗證:

cl <- makeCluster(8, type = "SOCK") 
registerDoSNOW(cl) 
system.time(mods <- foreach(x = 1:2, .packages = "glmnet") %dopar% { 
    idx <- Xclass == x 
    cv.glmnet(Xdat[idx,], Ydat[idx], nfolds = 4, parallel = FALSE) 
}) 
stopCluster(cl) 

對於兩個系統時間,我只能得到一個非常小的差異。

平行採取的是?或者我需要明確使用嵌套操作符?問題:如果羣集對象中有8個核心可用,並且foreach循環包含兩個任務,那麼每個任務將給予1個核心(其餘6個核心保持空閒),還是每個任務將被賦予4個核心總共使用了8個核心)?查詢在特定時間使用多少個核心的方法是什麼?

+3

'foreach'發送每個任務到一個核心。因此,只有一個核心可用於'cv.glmnet'。如果你想要嵌套並行化,你需要在'foreach'級別執行:http://cran.r-project.org/web/packages/foreach/vignettes/nested.pdf – Roland

+0

所以 - 澄清 - 我需要手動實施交叉驗證程序?如果是這樣,那就是我所懷疑的。 – dynamo

回答

3

在您的並行交叉驗證示例中,cv.glmnet本身不會並行運行,因爲沒有在羣集工作程序中註冊每個並行後端。外部的foreach循環將平行運行,但不是cv.glmnet函數中的foreach循環。

要使用doSNOW的外部和內部foreach循環,您可以使用clusterCall初始化雪集羣工人:

cl <- makeCluster(2, type = "SOCK") 
clusterCall(cl, function() { 
    library(doSNOW) 
    registerDoSNOW(makeCluster(2, type = "SOCK")) 
    NULL 
}) 
registerDoSNOW(cl) 

這將註冊doSNOW的主人和工人都讓每次調用cv.glmnet將在指定parallel=TRUE時在雙人羣集上執行。

嵌套並行處理的技巧是避免創建過多的進程和超額訂閱CPU(或多個CPU),因此在註冊並行後端時需要小心。我的例子對於具有四個內核的CPU來說是合理的,即使總共創建了六個工作者,因爲在內部foreach循環執行時,「外部」工作人員不會做太多工作。在集羣上運行以使用doSNOW爲每個節點啓動一個工作者時很常見,然後使用doMC在每個節點上爲每個核心啓動一個工作者。

請注意,您的示例沒有使用太多的計算時間,所以使用兩級並行性並不值得。我會用一個更大的問題來確定不同方法的好處。