From: Jan M. <jmo...@te...> - 2013-11-09 16:06:37
|
On Sat, 2013-11-09 at 10:25 -0500, Douglas Katzman wrote: > Nice code, but at a glance I can see that your problem is that the global > symbol *R* is used as your generator state, therefore forcing > materialization of all potential bignums. > I hacked it up a little bit and halved the runtime of (bench 50000000). > > In practice, you should make a macro > (WITH-GENERATOR (R) ...) > which expands to provide UNIFORM_REAL, UNIFORM_NAT, UNIFORM_BIT as lexical > macros within its body. > ("Do as I say, not as I do") > > Attached diffs will get you started. When noticing the defvar, I had a similar idea. I went with local functions which, on my system, also achieved halving the runtime (and consing): (defun compiled-mcmc/local-functions (N) (flet ((make-generator () (logand 8682522807148012 +mask+))) (let ((r (make-generator))) (labels ((random_next (r) (logand (+ (* r +multiplier+) +addend+) +mask+)) (uniform_bit () (logand (select (setf r (random_next r)) 1) 1)) (->double/52 (r) (/ (ash r (- 52 +width+)) +expt-2-52d0+)) (uniform_real () (->double/52 (setf r (random_next r))))) UNMODIFIED-REST-OF-THE-BODY)))) Kind regards, Jan |