配列の並列MAP処理 - lisp-cookbook-ja/common-lisp GitHub Wiki

一つの配列を複数のタスクに分けてMAP処理する例です。

下記の例では、CLiki:lparallelCLiki:Xecto を利用しています。

;;; #("1" "2" "3" ...)というような整数を文字列にしたものを要素にもつ配列
(declaim ((simple-vector 100000) *number-strings*))
(defvar *number-strings*
  (make-array 100000))

;; 初期化
(dotimes (i 100000)
  (setf (svref *number-strings* i)
        (write-to-string i)))

(aref *number-strings* 100)
;=>  "100"

lparallel

(setf lparallel:*kernel* (lparallel:make-kernel 2)) ;; ワーカーの数を設定

処理例

(reduce #'+
  (lparallel:pmap  '(simple-array integer (100000))
                   #'parse-integer
                   *number-strings*))
;⇒ 4999950000
#|------------------------------------------------------------|
Evaluation took:
  0.025 seconds of real time
  0.044003 seconds of total run time (0.044003 user, 0.000000 system)
  176.00% CPU
  60,653,268 processor cycles
  7,223,200 bytes consed

Intel(R) Core(TM)2 Duo CPU     P8600  @ 2.40GHz
 |------------------------------------------------------------|#

reduceも並列にした場合

(lparallel:preduce  #'+
  (lparallel:pmap  '(simple-array integer (100000))
                   #'parse-integer
                   *number-strings*))
;⇒ 4999950000
#|------------------------------------------------------------|
Evaluation took:
  0.025 seconds of real time
  0.036002 seconds of total run time (0.036002 user, 0.000000 system)
  144.00% CPU
  58,463,136 processor cycles
  7,224,768 bytes consed

Intel(R) Core(TM)2 Duo CPU     P8600  @ 2.40GHz
 |------------------------------------------------------------|#

Xecto

ライブラリの導入方法 (今のところSBCLのみ対応)

処理例

(defconstant max-threads 2)

(reduce #'+
  (parallel-future:with-context (max-threads) ;max-threadsの値まで並列実行
    (parallel:map '(simple-array integer (100000))
                  #'parse-integer
                  *number-strings*)))
;⇒ 4999950000
#|------------------------------------------------------------|
Evaluation took:
  0.051 seconds of real time
  0.080005 seconds of total run time (0.076005 user, 0.004000 system)
  156.86% CPU
  121,893,030 processor cycles
  4,047,616 bytes consed

Intel(R) Core(TM)2 Duo CPU     P8600  @ 2.40GHz
 |------------------------------------------------------------|#
;=>  4999950000

reduceも並列にした場合

(parallel-future:with-context (max-threads) ;max-threadsの値まで並列実行
  (parallel:reduce #'+
                   (parallel:map '(simple-array integer (100000))
                                 #'parse-integer
                                   *number-strings*)
                   0))
;⇒ 4999950000
#|------------------------------------------------------------|
Evaluation took:
  0.041 seconds of real time
  0.080005 seconds of total run time (0.080005 user, 0.000000 system)
  195.12% CPU
  97,143,192 processor cycles
  3,945,728 bytes consed

Intel(R) Core(TM)2 Duo CPU     P8600  @ 2.40GHz
 |------------------------------------------------------------|#

並列にしない場合

(reduce #'+
        (map '(simple-array integer (100000))
             #'parse-integer
             *number-strings*))
;⇒ 4999950000
#|------------------------------------------------------------|
Evaluation took:
  0.068 seconds of real time
  0.068004 seconds of total run time (0.064004 user, 0.004000 system)
  100.00% CPU
  162,015,912 processor cycles
  3,978,496 bytes consed

Intel(R) Core(TM)2 Duo CPU     P8600  @ 2.40GHz
 |------------------------------------------------------------|#