簡體   English   中英

R H2O - 內存管理

[英]R H2O - Memory management

我試圖通過R使用H2O來使用一個大數據集(~10GB)的子集構建多個模型。 數據是一年的數據,我正在嘗試建立51個模型(即第1周訓練,第2周預測等),每周約有1.5-250萬行,有8個變量。

我在循環中完成了這個,我知道這並不總是R中最好的方法。我發現的另一個問題是H2O實體會積累先前的對象,所以我創建了一個函數來刪除所有這些除了主數據組。

h2o.clean <- function(clust = localH2O, verbose = TRUE, vte = c()){
  # Find all objects on server
  keysToKill <- h2o.ls(clust)$Key
  # Remove items to be excluded, if any
  keysToKill <- setdiff(keysToKill, vte)
  # Loop thru and remove items to be removed
  for(i in keysToKill){
    h2o.rm(object = clust, keys = i)

    if(verbose == TRUE){
      print(i);flush.console()

    }    
  }
  # Print remaining objects in cluster.
  h2o.ls(clust)
}

該腳本運行良好一段時間然后崩潰 - 通常抱怨內存不足和交換到磁盤。

這里有一些偽代碼來描述這個過程

# load h2o library
library(h2o)
# create h2o entity
localH2O = h2o.init(nthreads = 4, max_mem_size = "6g")
# load data
dat1.hex = h2o.importFile(localH2O, inFile, key = "dat1.hex")

# Start loop
for(i in 1:51){
# create test/train hex objects
train1.hex <- dat1.hex[dat1.hex$week_num == i,]
test1.hex <- dat1.hex[dat1.hex$week_num == i + 1,]
# train gbm
dat1.gbm <- h2o.gbm(y = 'click_target2', x = xVars, data = train1.hex
                      , nfolds = 3
                      , importance = T
                      , distribution = 'bernoulli' 
                      , n.trees = 100
                      , interaction.depth = 10,
                      , shrinkage = 0.01
  )
# calculate out of sample performance
test2.hex <- cbind.H2OParsedData(test1.hex,h2o.predict(dat1.gbm, test1.hex))
colnames(test2.hex) <- names(head(test2.hex))
gbmAuc <- h2o.performance(test2.hex$X1, test2.hex$click_target2)@model$auc

# clean h2o entity
h2o.clean(clust = localH2O, verbose = F, vte = c('dat1.hex'))

} # end loop

我的問題是,在一個獨立的實體中管理數據和內存的正確方法是什么(這不是在hadoop或集群上運行 - 只是一個大的EC2實例(~64gb RAM + 12個CPU))過程? 我應該在每次循環后殺死並重新創建H2O實體(這是原始過程但每次從文件中讀取數據每次迭代增加約10分鍾)? 在每次循環后是否有正確的方法來垃圾收集或釋放內存?

任何建議,將不勝感激。

這個答案適用於原始的H2O項目(發布2.xyz)。

在最初的H2O項目中,H2O R包在H2O集群DKV(分布式鍵/值存儲)中創建了許多臨時H2O對象,其前綴為“Last.value”。

這些在Web UI的Store View中和從R調用h2o.ls()都可見。

我建議做的是:

  • 在每個循環迭代的底部,使用h2o.assign()對要保存到已知鍵名的任何內容進行深層復制
  • 使用h2o.rm()刪除任何你不想保留的內容,特別是“Last.value”temps
  • 在循環中的某個地方顯式調用gc()

這是一個為您刪除Last.value臨時對象的函數。 傳入H2O連接對象作為參數:

removeLastValues <- function(conn) {
    df <- h2o.ls(conn)
    keys_to_remove <- grep("^Last\\.value\\.", perl=TRUE, x=df$Key, value=TRUE)
    unique_keys_to_remove = unique(keys_to_remove)
    if (length(unique_keys_to_remove) > 0) {
        h2o.rm(conn, unique_keys_to_remove)
    }
}

以下是H2O github存儲庫中R測試的鏈接,該存儲庫使用此技術並且可以無限期運行而不會耗盡內存:

https://github.com/h2oai/h2o/blob/master/R/tests/testdir_misc/runit_looping_slice_quantile.R

截至2015年12月15日的新建議:更新到最新的穩定版(Tibshirani 3.6.0.8或更高版本)。 我們已經完全重寫了R&H2O如何處理內部臨時變量,並且內存管理更加順暢。

Next:H2O temps可以通過R死變量保持“活着”...所以每次循環迭代運行一個R gc()。 一旦R的GC移除死變量,H2O將回收該內存。

之后,您的群集應該只保留特定命名的內容,例如已加載的數據集和模型。 這些你需要大致刪除它們,以避免在K / V存儲中累積大數據。

如果您有任何問題,請通過發布到Google論壇h2o流來告訴我們: https ://groups.google.com/forum/#!forum / h2ostream

懸崖

這個問題的最新答案是你應該只使用h2o.grid()函數而不是編寫循環。

使用H2O新版本(目前為3.24.0.3),他們建議使用以下建議:

my for loop {
 # perform loop

 rm(R object that isn’t needed anymore)
 rm(R object of h2o thing that isn’t needed anymore)

 # trigger removal of h2o back-end objects that got rm’d above, since the rm can be lazy.
 gc()
 # optional extra one to be paranoid.  this is usually very fast.
 gc()

 # optionally sanity check that you see only what you expect to see here, and not more.
 h2o.ls()

 # tell back-end cluster nodes to do three back-to-back JVM full GCs.
 h2o:::.h2o.garbageCollect()
 h2o:::.h2o.garbageCollect()
 h2o:::.h2o.garbageCollect()
}

來源: http//docs.h2o.ai/h2o/latest-stable/h2o-docs/faq/general-troubleshooting.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM