下面的程序似乎效率很低。与 SBCL 1.0.53 相比,它需要 28.980 秒的 GC 时间,而非 GC 时间为 6.361 秒。
(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 创建 cons pool 将减少内存分配。
理想情况下,SBCL 支持某些数据结构(如 vec3)作为数组元素的非描述符表示会很好。