タスクを並列に実行する - lisp-cookbook-ja/common-lisp GitHub Wiki

下記は、それぞれのタスクに依存性がなく、単に並列に実行する例です。

CLiki:bordeaux-threadsCLiki:Xecto を利用しています。

CLiki:bordeaux-threadsは、処理系依存の記述をカバーする互換性向上のためのパッケージです。

bordeaux-threads

CLiki:bordeaux-threads ライブラリの導入方法

(ql:quickload :bordeaux-threads)

スレッドを生成して、ジョインする、というパターンです。

スレッドは、処理系依存ですが、make-threadでスレッドを生成し即実行という実装が多いようです。

(let ((out #.*standard-output*))
  (let ((task1 (bt:make-thread (lambda ()
                                 (format out "~&start1 ...~%")
                                 (sleep 8)
                                 (format out "~&... end1~%"))))
        (task2 (bt:make-thread (lambda ()
                                 (format out "~&start2 ...~%")
                                 (sleep 5)
                                 (format out "~&... end2~%")))))
    (bt:join-thread task1)
    (bt:join-thread task2)))
;->  start1 ...
;    start2 ...
;    ... end2
;    ... end1
;
;=>  NIL

lparallel

CLiki:lparallel ライブラリの導入方法

(ql:quickload :lparallel)
(setf lparallel:*kernel* (lparallel:make-kernel 2))  ;; ワーカーの数を設定
(let ((out #.*standard-output*))
  (lparallel:plet ((task1 (progn
                            (format out "~&start1 ...~%")
                            (sleep 8)
                            (format out "~&... end1~%")))
                   (task2 (progn
                            (format out "~&start2 ...~%")
                            (sleep 5)
                            (format out "~&... end2~%"))))
      task1
      task2
      nil))
;->  start2 ...
;    start1 ...
;    ... end2
;    ... end1
;
;=>  NIL

Xecto

CLiki:Xecto ライブラリの導入方法(現在のところSBCLのみ対応)

(defconstant max-threads 2)

(let ((out #.*standard-output*))
  (parallel-future:with-context (max-threads) ;max-threads の値まで並列実行
    (parallel:let ((task1 (progn
                            (format out "~&start1 ...~%")
                            (sleep 8)
                            (format out "~&... end1~%")))
                   (task2 (progn
                            (format out "~&start2 ...~%")
                            (sleep 5)
                            (format out "~&... end2~%")))
                   (:parallel t))
      (declare (ignore task1 task2))
      ;; ボディは空
      )))
;->  start1 ...
;    start2 ...
;    ... end2
;    ... end1
;
;=>  NIL