Common Lisp에서 스트림 병렬 처리

내 컴퓨터에는 많은 코어가 있지만 전체 데이터를 저장하기에 충분한 RAM이 없습니다. 그래서 저는 일반적으로 스트림의 데이터를 병렬로 처리해야 합니다. 예를 들어 태국어 텍스트를 한 줄씩 읽고 각 코어에서 실행되는 프로세서로 디스패치합니다.

Clojure에서는 pmap이 지연 시퀀스에서 작동하기 때문에 pmap을 사용할 수 있습니다. 그러나 게으른 시퀀스와 함께 Common Lisp에서 Lparallel의 pmap을 사용하는 것은 예제에 없었습니다. 그래서 대신 보르도 스레드와 ChanL 채널을 사용했습니다. 그것은 효과가 있었다. 그래도 스트림을 병렬로 처리하고 싶을 때마다 스레드와 채널을 처리하는 반복적인 코드를 작성해야 했습니다. 지저분해 보일 뿐만 아니라 많은 버그가 있었습니다.

그래서 스레드 및 채널 관리를 래핑하기 위해 stream-par-procs 이라는 작은 라이브러리를 만들었습니다. 다이어그램에 표시된 것처럼 리더는 스트림에 대한 라인을 읽고 시스템은 다른 프로세서에 라인을 전달하고 마지막으로 수집기가 최종 결과를 생성합니다.



따라서 코드는 아래와 같습니다.

(with-open-file (f #p"hello.txt")
  (process f
       (lambda (elem state send-fn)
         (declare (ignore state))
         (funcall send-fn (length elem)))
       :collect-fn (lambda (n sum)
             (+ n sum))
       :init-collect-state-fn (lambda () 0)
       :num-of-procs 8))


프로세서에서 실행할 함수, 수집기에서 실행할 함수, 상태 초기화를 위한 기타 함수만 정의하면 됩니다. 예를 들어 모든 프로세서가 END-OF-STREAM을 보낼 때 수집기 스레드에 합류하는 세부 정보를 숨깁니다.

간단히 말해서 stream-par-procs는 스레드 및 채널 관리 코드를 재사용하여 버그를 줄이고 Common Lisp에서 스트림을 병렬로 처리하는 것을 더 편리하게 만듭니다.

좋은 웹페이지 즐겨찾기