以下のプログラムは非常に非効率的です。SBCL 1.0.53 では 6.361 秒の非 GC 時間とは対照的に、GC 時間は 28.980 秒かかります。
(deftype vec3 () '(simple-array double-float (3)))
(declaim (inline make-vec3 vec3-zero
vec3-x vec3-y vec3-z
vec3-+))
(defun make-vec3 (x y z)
(declare (optimize (speed 3) (safety 0)))
(make-array 3 :element-type 'double-float
:initial-contents (list x y z)))
(defun vec3-zero ()
(make-vec3 0.0d0 0.0d0 0.0d0))
(defun vec3-x (x)
(declare (optimize (speed 3) (safety 0)))
(declare (type (simple-array double-float (3)) x))
(aref x 0))
(defun vec3-y (x)
(declare (optimize (speed 3) (safety 0)))
(declare (type (simple-array double-float (3)) x))
(aref x 1))
(defun vec3-z (x)
(declare (optimize (speed 3) (safety 0)))
(declare (type (simple-array double-float (3)) x))
(aref x 2))
(defun vec3-+ (a b)
(declare (optimize (speed 3) (safety 0)))
(make-vec3 (+ (vec3-x a) (vec3-x b))
(+ (vec3-y a) (vec3-y b))
(+ (vec3-z a) (vec3-z b))))
;; main
(defun image (x y)
(make-array (* x y) :element-type 'vec3 :initial-element (vec3-zero)))
(defun add (to from val)
(declare (type (simple-array vec3 (*)) to from)
(type vec3 val)
(optimize (speed 3) (safety 0)))
(let ((size (array-dimension to 0)))
(dotimes (i size)
(setf (aref to i) (vec3-+ (aref from i) val)))))
(defun main ()
(let ((to (image 800 800))
(x (make-vec3 1.0d0 1.0d0 1.0d0)))
(time (dotimes (i 200)
(add to to x)))
(print (aref to 0))))
時間:
* (main)
Evaluation took:
39.530 seconds of real time
35.340237 seconds of total run time (25.945526 user, 9.394711 system)
[ Run times consist of 28.980 seconds GC time, and 6.361 seconds non-GC time. ]
89.40% CPU
83,778,297,762 processor cycles
46 page faults
6,144,014,656 bytes consed
#(200.0d0 200.0d0 200.0d0)
#(200.0d0 200.0d0 200.0d0)
vec3 の抽象化を維持しながら、より効率的な方法で計算する方法はありますか?
たとえば、マクロを使用して Worker/Wrapper 変換を実装すると、vec3 conses を排除できます。
別の方法として、vec3 のコンス プールを作成すると、メモリ割り当てが減少します。
理想的には、SBCL が vec3 のような一部のデータ構造の非記述子表現を配列要素としてサポートするとよいでしょう。