2017-12-20 12 views
0

joblib을 사용하여 임의의 사용자 지정 포리스트 구현 트레인을 병렬로 만들려고합니다.joblib 속도 저하 조사

작업이 당황스럽고 평행하므로 속도 향상이 joblib에 너무 어려워서는 안된다고 가정했습니다. 배치 및 증분 경우 두 개 이상의 작업을 사용하는 경우

class RandomForest(object): 
    def __init__(self, settings, data): 
     self.forest = [None] * settings.n_trees 
     self.parallel = Parallel(n_jobs=settings.njobs, backend="threading") 

    def fit(self, data, train_ids_current_minibatch, settings, param, cache): 
     self.forest = self.parallel(
      delayed(_parallel_build_trees_batch)(
       i_t, data, train_ids_current_minibatch, settings, param, cache) 
      for i_t, tree in enumerate(self.forest)) 

    def partial_fit(self, data, train_ids_current_minibatch, settings, param, cache): 
     self.forest = self.parallel(
      delayed(_parallel_build_trees_partial)(
       tree, i_t, data, train_ids_current_minibatch, settings, param, cache) 
      for i_t, tree in enumerate(self.forest)) 

그러나, 훈련이 훨씬 느립니다 :

는 여기에 몇 가지 예제 코드입니다. 데이터 및 캐시 인수는 (큰) numpy 배열을 포함하는 dict입니다. 그래서 그 원인인지 궁금합니다. 맞춤 기능 NumPy와/scipy 코드를 많이 사용하기 때문에

내가 multiprocessing.Pool를 사용하여 동일한 코딩 시도하고 JOBLIB의 threading 백엔드를 사용하지 않는 한 결과, 더 악화되어, 나는 가정합니다.

감속/디버그 방법에 대한 아이디어가 있으십니까?

+0

내 게시물에 귀하의 질문에 대한 답변이 나왔습니까? – hansaplast

답변

1

귀하의 분석은 저에게 맞는 것처럼 보입니다. 속도 저하는 큰 물체 인 datacache으로 인해 발생합니다. 이제 다중 처리 환경에서 공유 메모리가 없으므로 이러한 객체를 어떻게 든 공유해야합니다. 파이썬은 shared objects을 통해이를 지원합니다 : 실제로 그 객체를 보유하고있는 "메인 프로세스"가 있습니다. 그러나 다른 프로세스는 어떤 메커니즘을 통해 모든 업데이트를 보내야합니다. (객체가 절편 처리 된 다음 파이프 또는 대기열을 통해 전송 됨) 속도가 느려집니다.

나는 당신을 위해 몇 가지 옵션을 참조하십시오이 파티션를 사용하므로

  • 이 코드를 변환 : 나는 임의 숲에 익숙하지 않다. 나는 모든 프로세스가 초기 데이터 세트로 data을 가지고 있다고 생각하고 "최적"을 찾으려고 노력한다. 프로세스 1을 밀어 모든 "유형 A"최적 값을 찾고 2를 처리하여 모든 "유형 B"최적 값을 찾은 다음 모든 프로세스를 보자. 파티션이 작동하지 않는 경우에, 어쩌면 당신은 할 수 : 파일 rf_process_x.txt에서 디스크에 자신의 연구 결과를 작성하는 것은 다음은 을 (this page에 마지막 예를 참조)를 사용하므로
  • 이 코드를 변환 공유 메모리 상태를 필요가 없습니다
      시작
    1. N 노동자는 모든 프로세스가 자신을 위해 자신의 data 세트를 빌드 (그래서 공유 메모리에없는) 당신이 task_queue, 예에 "작업"을 넣어 주 과정에서
    2. 를 처리 이 특정 매개 변수 집합을 사용하여 임의의 포리스트를 찾습니다. 작업자는 task_queue에서 작업을 가져 와서 계산하고 그 결과를 result_queue에 저장합니다. 이러한 개체를 절곡하여 부모 프로세스에서 작업자 프로세스로 파이프를 통해 전송해야하므로 작업과 결과가 느린 경우에만 속도가 빨라집니다.
  • 사용 memmapping joblibs : 귀하의 작업이 구속 하지 CPU의 경우 디스크에 개체를 덤프 다음 줄 Joblibs supports 각 (해당 파일
  • 에 메모리 매핑 개체 액세스 무거운 디스크 또는 네트워크 작업을 수행) 멀티 스레딩으로 이동할 수 있습니다. 이렇게하면 공유 메모리가 있습니다.그러나 지금까지 내가 CPU가 결합되어 당신을 볼 수 있고, "GIL 잠금"문제로 실행됩니다, 당신은 임의 숲을 속도의 다른 방법을 찾을 수 있습니다
  • (CPython에 오직 하나 개의 스레드가 한 번에 실행) 예 this SO answer 몇 가지 언급했습니다.