Hello,
could you post some timing results?
(time (bsmc ...)) -> ?
Maybe the bottleneck is mainly the random number generator? I have written
the following routine GASDEV which is about twice as fast as
ONE-NORMAL-RAND on my machine (and is hopefully a reasonable replacement to
it - note that I am no random number expert).
(let ((stored nil))
(declare (optimize speed))
(defun gasdev ()
"Returns Gaussian noise with zero mean and unit variance."
(if stored
(shiftf stored nil)
(loop (let* ((v1 (- (random 2d0) 1d0))
(v2 (- (random 2d0) 1d0))
(r (+ (* v1 v1) (* v2 v2))))
(declare (type (double-float (0d0) (2d0)) r))
(when (< r 1d0)
(let ((fac (sqrt (/ (* -2d0 (the (double-float * (0d0)) (log
r))) r))))
(setf stored (* v1 fac))
(return (* v2 fac)))))))))
(time (loop repeat 1000000 summing (one-normal-rand)))
; Evaluation took:
; 3.37 seconds of real time
; 3.120526 seconds of user run time
; 0.215968 seconds of system run time
; 6,064,384,884 CPU cycles
; [Run times include 0.29 seconds GC run time]
; 0 page faults and
; 119,593,088 bytes consed.
(time (loop repeat 1000000 summing (gasdev)))
; Evaluation took:
; 1.79 seconds of real time
; 1.634751 seconds of user run time
; 0.152977 seconds of system run time
; 3,233,807,392 CPU cycles
; [Run times include 0.14 seconds GC run time]
; 0 page faults and
; 72,744,448 bytes consed.
There is not much to be accelerated here any more using CMUCL's own random
number generator, because of:
(time (loop repeat 1000000 summing (random 1d0) double-float))
; Evaluation took:
; 1.05 seconds of real time
; 0.98985 seconds of user run time
; 0.052992 seconds of system run time
; 1,889,576,568 CPU cycles
; [Run times include 0.09 seconds GC run time]
; 0 page faults and
; 32,000,208 bytes consed.
If C has simpler and faster (but maybe worse?) random number generators,
then this might be the source of the observed speed difference.
Yours, Nicolas.