Codriding Parallel gem(Process)

7419 단어 codereadingRuby
지난번Cording Parallel gem(Thread)에서 Thread Base의 병렬 처리를 추적하였으며, 이번에는 Process Base를 추적할 것입니다.

대상

  • Parallel
  • https://github.com/grosser/parallel
  • v1.9.0
  • MRI 2.3
  • MacOS
  • Thread와 Process의 차이점과 차이점을 아는 사람을 대상으로 합니다.
    그 일대는 어딘가의 보도를 읽어 보세요.

    용례


    코드를 읽을 때, 나는 다음 코드의 실행 상황을 추적하기로 결정했다.
    list = ['a','b','c']
    log.info 'start'
    Parallel.map(list, in_processes: 2) do |one_letter|
      log.info one_letter
    end
    log.info 'finish'
    
    실행 결과는 다음과 같다.
  • pidProcess.pid
  • tidThread.current.object_id

  • Parallel.map


    여기 앞에는 이미 읽었으니 개요를 조목조목 나누어 써라.
  • CPU 코어 수보다 적은 수의 병렬 처리 Job 선택
  • Thread 또는 Process 선택
  • 이번에는 선택 가능한 지정in_processes이므로 실행Parallel.work_in_processes
  • Parallel.work_in_processes


    이 앞은 너무 복잡해서 문장으로 설명할 수 없어서 그림을 그렸다.

    1. new - JobFactory.new


    먼저 게시판에 JobFactory를 쓰십시오.새 옷으로 갈아입고 있어요.
    parallel.rb#L230
    def map(source, options = {}, &block)
      # ...
    
      job_factory = JobFactory.new(source, options[:mutex])
    

    2. option[:size]의 수량은 fork-Processs 사전 제작


    Process 를 사전 신청했습니다.
    Apache와 Prefork은 별개의 문제로 다릅니다.
    Fork Process의 경우 메모리 공간 자체를 공유할 수 없음프로세스 통신 때문에 문제가 있습니다.
    Parallel은 파이프로 해결한다.
    구체적으로 work_in_processes 내에서 create_workers를 호출하여 병렬 수분의 워커 대상을 만든다.
    parallel.rb#L324
    def work_in_processes(job_factory, options, &blk)
      workers = if options[:isolation]
        [] # we create workers per job and not beforehand
      else
        create_workers(job_factory, options, &blk)
      end
    
    isolation 스태프를 사전에 제작하지 않고 각 라인에 따라 순서대로 제작한다.이번 용례에 없으면 나는 무시할 것이다.create_workers에서 job_factory에서 임무를 얻고 직원에게 분배한다.
    내부에서 구체적으로 무엇을 하고 있는지 잠시 후에 쓰겠습니다.

    3. new를 통해 pid와 링크 관리 - 하위 프로세스의worker 실례 제작

    worker 방법을 사용하여 하위 프로세스의 fork와 워커 대상을 만듭니다.
    parallel.rb#L391
    def worker(job_factory, options, &block)
      # ...
    
      pid = Process.fork do
        # ...
      end
      # ...
    
      Worker.new(parent_read, parent_write, pid)
    end
    
    Worker 객체는 상위 프로세스의 inout 입출력 객체와 전달되며 상위 프로세스와 하위 프로세스의 데이터 교환이 진행 중입니다.
    데이터 형식은 Ruby가 준비한 Marshal로 진행dump/load(그림9 참조)

    5. 루틴 시작 [:size] 수량 - 부모 프로세스의 루틴에 하위 프로세스를 할당합니다


    부모 프로세스는 여러 개의 하위 프로세스를 가지고 있으며, 동시에 하위 프로세스는 데이터와 처리를 동기화할 수 없습니다.
    따라서 부모 프로세스를 다중 루틴화하여 하나의 루틴에 하위 프로세스를 분배하여 병렬 처리할 수 있도록 합니다.
    parallel.rb#L334
    UserInterruptHandler.kill_on_ctrl_c(workers.map(&:pid), options) do
      in_threads(options) do |i|
        worker = workers[i]
    
        # ....
      end
    end
    
    UserInterruptHandler.kill_on_ctrl_c는 신호를 보내서 처리를 중단하는 메커니즘이다.
    다음 처리SIGINT(Ctrol-C)로 Process를 모두 죽이십시오.
    신호 자체는 :interrupt_signal 옵션으로 변경할 수 있습니다.

    좋은 웹페이지 즐겨찾기