2016-09-16 7 views
3

foreach 루프 내부에서 h2o.gbm을 여러 번 호출하는 것이 순진하다고 생각했습니다. 그러나 이상한 오류가 발생했습니다.foreach 루프 내에서 h2o 알고리즘을 실행 하시겠습니까?

Error in { : 
     task 3 failed - "java.lang.AssertionError: Can't unlock: Not locked!" 

library(foreach) 
library(doParallel) 
library(doSNOW) 

Xtr.hf = as.h2o(Xtr) 
Xval.hf = as.h2o(Xval) 

cl = makeCluster(6, type="SOCK") 
registerDoSNOW(cl) 
junk <- foreach(i=1:6, 
      .packages=c("h2o"), 
      .errorhandling = "stop", 
      .verbose=TRUE) %dopar% 
{ 
    h2o.init(ip="localhost", nthreads=2, max_mem_size = "5G") 
    for (j in 1:3) { 
    bm2 <- h2o.gbm(
    training_frame = Xtr.hf, 
    validation_frame = Xval.hf, 
    x=2:ncol(Xtr.hf), 
    y=1,   
    distribution="gaussian", 
    ntrees = 100, 
    max_depth = 3, 
    learn_rate = 0.1, 
    nfolds = 1) 
    } 
    h2o.shutdown(prompt=FALSE)  
    return(iname) 
} 
stopCluster(cl) 

답변

3

참고 아래 코드 : R의 병렬 foreach는이 가능성을 잘 사용하지만, 나는 그 이유를 설명, 첫번째 질문을 답변 해 드리겠습니다. (BTW 내가 "클러스터"를 사용하는 경우이 물음표에서 H2O 클러스터 (로컬 시스템에있는 경우 라 할지라도)와 R "클러스터"는 아님)를 말합니다.

library(foreach) 
library(doParallel) 
library(doSNOW) 
library(h2o) 

h2o.init(ip="localhost", nthreads=-1, max_mem_size = "5G") 

Xtr.hf = as.h2o(Xtr) 
Xval.hf = as.h2o(Xval) 

cl = makeCluster(6, type="SOCK") 
registerDoSNOW(cl) 
junk <- foreach(i=1:6, 
      .packages=c("h2o"), 
      .errorhandling = "stop", 
      .verbose=TRUE) %dopar% 
{ 
    for (j in 1:3) { 
    bm2 <- h2o.gbm(
    training_frame = Xtr.hf, 
    validation_frame = Xval.hf, 
    x=2:ncol(Xtr.hf), 
    y=1,   
    distribution="gaussian", 
    ntrees = 100, 
    max_depth = 3, 
    learn_rate = 0.1, 
    nfolds = 1) 

    #TODO: do something with bm2 here? 

    } 
    return(iname) #??? 
} 
stopCluster(cl) 

즉 : 코드, 의도를 가정하고 모든 모델을 만들 수됩니다 단일 H2O 클러스터를 가지고 있었다 개요 형태 :

  • 시작 H2O, 그리고에로드 XtrXval
  • 시작하여 R 클라이언트에서 6 개 스레드 각 스레드에서
  • 만드는 3 개 GBM 모델 (각각 하나씩)

의도하지 않았다고 생각한 h2o.shutdown() 명령을 삭제했습니다 (방금 만든 모델을 H2O 클러스터를 종료하면 삭제됨). 그리고 나는 당신이 당신의 모델로 무엇을하고 싶어 할지도 모르는 곳을 강조했습니다. 그리고 나는 모든 스레드 시스템에 H2O를 준 단지 2

당신 병렬 H2O 모델을 만들 수 없습니다 (즉 h2o.init()에서 nthreads=-1입니다)하지만 종료로는, 일반적으로 나쁜 생각 자원을위한 싸움. 한 번에 하나씩 수행하는 것이 더 좋으며 H2O의 자체 병렬 코드를 사용하여 클러스터를 통해 계산을 분산하는 것이 좋습니다. (클러스터가 단일 머신 일 때 이것은 매우 효율적입니다.)

사실 R에서 병렬 루프를 만드는 데 문제가있어, H2O가 작동하는 방식을 놓쳤다 고 생각하게 만듭니다. Java로 작성된 서버이고 R은 API 호출을 보내는 가벼운 클라이언트입니다. GBM 계산은 R에서는 수행되지 않습니다. 그들은 모두 Java 코드로 수행됩니다.

코드를 해석하는 다른 방법은 여러 개의 H2O 인스턴스 즉 여러 개의 H2O 클러스터를 실행하는 것입니다. 이것은 일련의 기계를 가지고 있고 H2O 알고리즘이 다중 노드 클러스터에서 잘 확장되지 않는다는 것을 알고 있으면 좋은 생각 일 수 있습니다. 하나의 컴퓨터에서이 작업을 수행하는 것은 거의 잘못된 생각입니다.

library(foreach) 
library(doParallel) 
library(doSNOW) 

cl = makeCluster(6, type="SOCK") 
registerDoSNOW(cl) 
junk <- foreach(i=1:6, 
      .packages=c("h2o"), 
      .errorhandling = "stop", 
      .verbose=TRUE) %dopar% 
{ 
    library(h2o) 
    h2o.init(ip="localhost", port = 54321 + (i*2), nthreads=2, max_mem_size = "5G") 

    Xtr.hf = as.h2o(Xtr) 
    Xval.hf = as.h2o(Xval) 

    for (j in 1:3) { 
    bm2 <- h2o.gbm(
    training_frame = Xtr.hf, 
    validation_frame = Xval.hf, 
    x=2:ncol(Xtr.hf), 
    y=1,   
    distribution="gaussian", 
    ntrees = 100, 
    max_depth = 3, 
    learn_rate = 0.1, 
    nfolds = 1) 

    #TODO: save bm2 here 
    } 
    h2o.shutdown(prompt=FALSE)  
    return(iname) #??? 
} 
stopCluster(cl) 

이제 개요는 다음과 같습니다 :

  • 는 각 스레드에서 6 개 R 스레드
  • 만들기, H2O를 시작하지만, 인수를 위해, 이것은 당신이 (안된) 그것을 할 방법입니다 localhost에서 실행 중이지만 해당 클러스터에 고유 한 포트에서 실행중인 클러스터. (i*2은 실제로 각 H2O 클러스터가 실제로 두 개의 포트를 사용하기 때문입니다.)
  • 데이터를 H2O 클러스터에 업로드합니다 (즉, 클러스터마다 한 번씩 6 번 반복됩니다).
  • 3GBM 모델을 하나씩 만듭니다.
  • 해당 모델로 무언가를하십시오.
  • 현재 스레드에 대한 클러스터를 강제 종료하십시오.

당신이 당신의 컴퓨터에 12 개 이상의 스레드가있는 경우, 그리고 30 + GB 메모리, 데이터가 상대적으로 작은이 한 H2O 클러스터를 사용하여 직렬에서 12 개 GBM 모델을 만드는과 거의 같은 효율적입니다. 그렇지 않다면 나는 그것이 더 나쁠 것이라고 믿습니다. (그러나 6 개의 원격 컴퓨터에서 6 개의 H2O 클러스터를 미리 시작한 경우이 방법이 유용 할 수 있습니다.이를 수행하는 방법을 궁금해하고 있습니다. 나는 당신의 질문을보고)

참고 :! 효과적으로 포트를 무시 의미 h2o.init()에서 a bug이있는 한 현재 버전 (3.10.0.6)의로, 나는 위의 코드가 작동하지 않습니다 알고 . (해결 방법 : 명령 줄에서 6 개의 H2O 클러스터를 모두 미리 시작하거나 환경 변수에 포트를 설정하십시오.)

+0

감사합니다. 코드와 나의 유일한 차이점은'h2o.init (ip = "localhost", port = 54321 + (i * 2), ...)'입니다. 다른 포트를 지정하면 h2o가 각 스레드에 대해 별도의 클러스터를 작성합니다. – horaceT

+0

@horaceT 또한'as.h2o()'데이터 업로드는 for 루프 안에 있어야합니다. (필자는 그것이 필요한지 확실치 않지만 foreach 루프 안에'라이브러리 (h2o)'를 넣었습니다.) (포트 버그가 수정 될 때까지 코드는 작동하지 않을 것이라고 언급했듯이) –

+0

테스트하지는 않았지만 개념을 이해하고 싶습니다. 'h2o.init (...) '호출은 클러스터를 생성하고 각 클러스터는 하나의 스레드에만 연결됩니다. 동일한 클러스터 내에서 여러 스레드를 실행할 수 없습니다. 그게 어떻게 작동해야합니까? – horaceT