2016-03-01 34 views
3

下面的問題是一個非常詳細的問題與這裏描述的問題有關。 Previous QuestionR doParallel foreach工人超時錯誤,永不返回

使用Ubuntu Server 14.04 LTS 64位亞馬遜機器映像在R版本3.2.3的c4.8xlarge(36核心)上啓動。

考慮下面的代碼

library(doParallel) 
cl=makeCluster(35) 
registerDoParallel(cl) 

tryCatch({ 
    evalWithTimeout({ 
    foreach(i=1:10) %:% 
     foreach(j=1:50) %dopar% { 
     tryCatch({ 
      evalWithTimeout({ 
      set.seed(j) 
      source(paste("file",i,".R", sep = "")) # File that takes a long time to run 
      save.image(file=paste("file", i, "-run",j,".RData",sep="")) 
      }, 
      timeout=300); ### Timeout for individual processes 
     }, TimeoutException=function(ex) { 
      return(paste0("Timeout 1 Fail ", i, "-run", j)) 

     }) 
     } 
    }, 
    timeout=3600); ### Cumulative Timeout for entire process 
}, TimeoutException=function(ex) { 

    return("Timeout 2 Fail") 

}) 

stopCluster(cl) 

注意兩個超時異常的工作。我們注意到單個進程超時,如有必要,累計進程超時。

然而,我們發現,單個進程可以就未知原因後經過300秒沒有超時。請注意,單個進程超時可確保進程不會「花費很長時間」。結果,核心被這個單一進程佔用,並以100%運行,直到達到3600秒的累積超時。請注意,進程及其核心將被無限期地佔用,如果累積超時未到位,則foreach循環將無限期地繼續。達到累計時間後,將返回「超時2失敗」並繼續執行腳本。

問題:如果以這樣的方式,即使是個別超時機制不起作用,一個人如何重新啓動工人,以便它可以繼續單獨的工作進程「掛起」在並行處理中使用?如果無法重新啓動工作人員,工作人員能否以達到累計超時時間的方式停止工作?這樣做可以確保進程在延長的時間內不會持續「等待」達到累積超時,而只有單個「錯誤」進程正在運行。

其他信息 A「逃跑」過程或「掛起」工人被當場抓獲。使用htop查看進程,它具有以100%CPU運行的狀態。下面的鏈接是GDB回溯通話的過程

backtrace screenshot

問題截圖:就是在回溯確定了「失控」進程的原因是什麼?

回答

0

我多次嘗試讓evalWithTimeout在非常相似的環境下工作。我發現它是非常有問題的,特別是如果你使用數據庫連接或全局變量。然而,對我來說,什麼工作非常好,正在創建一個使用setTimeLimit的表達式。要正確使用它,您必須將它和您的功能一起包裝在{}中。這裏有一個例子:

foreach(...) %dopar% { 
    withCallingHandlers({ 
    setTimeLimit(360) 
    # your function goes here, runs for 360 seconds, or fails 
    }, 
    error = function(e) { 
    # do stuff to capture error messages here 
    } 
) 
} 

我用withCallingHandlers因爲堆棧跟蹤是非常有用的,並得到深入到發生了什麼。在我的錯誤函數中,我通常會做一些事情來適當地捕獲詳細的錯誤消息,以便我可以查看哪些事情和哪些事情正在破壞。

所以總結起來:

  1. setTimeLimit通常比evalWithTimeout更可靠
  2. 使用withCallingsHandlers爲您提供了錯誤處理和更詳細的輸出比tryCatch
  3. 切記妥善保存您的錯誤極好的選擇消息在某處有用並對其進行格式化,以便您可以看到真正發生的情況。